##
## clirc -- An IRC client in Python.
## buffer.py - Text history container and event handler.
##
## Copyleft 1997-2000 Teemu Kalvas <chery@s2.org>
##

import reloadable

class TextSpan:
    def __init__(self, str):
        if type(str) == type([]):
            self.spans = str
            return
        self.spans = []
        attr = 0
        i = 0
        j = 0
        for ch in str:
            if ch == '\002':
                if j > i:
                    self.spans.append((str[i:j], attr))
                attr = attr ^ 1
                i = j + 1
            elif ch == '\037':
                if j > i:
                    self.spans.append((str[i:j], attr))
                attr = attr ^ 2
                i = j + 1
            elif ch == '\026':
                if j > i:
                    self.spans.append((str[i:j], attr))
                attr = attr ^ 4
                i = j + 1
            elif (ord(ch) & 127) < 32:
                if j > i:
                    self.spans.append((str[i:j], attr))
                i = j + 1
            j = j + 1
        if j > i:
            self.spans.append((str[i:j], attr))

    def __len__(self):
        return reduce(lambda a, x: a + len(x[0]), self.spans, 0)

    def __getitem__(self, i):
        for sp in self.spans:
            l = len(sp[0])
            if i < l:
                return sp[0][i]
            i = i - l

    def __getslice__(self, i, j):
        rspans = []
        for sp in self.spans:
            ll = len(sp[0])
            if i < ll:
                if j <= 0:
                    return TextSpan(rspans)
                rspans.append((sp[0][i:j], sp[1]))
            i = max(0, i - ll)
            j = max(0, j - ll)
        return TextSpan(rspans)

    def __add__(self, str):
        spans = self.spans[:]
        if spans[-1][1]:
            spans.append((str, 0))
        else:
            spans[-1] = spans[-1][0] + str, 0
        return TextSpan(spans)

    def print_line(self, print_span, y):
        x = 0
        k = 0
        l = len(self.spans)
        while k < l:
            str, attr = self.spans[k]
	    print_span(y, x, str, attr)
	    x = x + len(str)
            k = k + 1

class Buffer(reloadable.Reloadable):
    def __init__(self, net, name):
        self.net = net
        self.name = name
        self.detect = 0
        self.log_notify = []
        self.start = 0
        self.threshold = 1024
        self.array = self.threshold * [None]
        self.pos = 0
        self.post_reload()

    def __getitem__(self, pos):
	if pos >= self.start:
	    if pos < self.pos:
		return self.array[pos - self.start]
	elif pos >= self.pos - self.threshold and pos >= 0:
	    return self.array[pos - self.start + self.threshold]
	return TextSpan('')

    def __len__(self):
        return self.pos

    def log_start(self):
	return max(0, self.pos - self.threshold + 1)

    def register(self, n):
        self.log_notify.append(n)

    def unregister(self, n):
        self.log_notify.remove(n)

    def pre_delete(self):
        for actor in self.log_notify[:]:
            actor.pre_delete()

    def log(self, str):
        self.slog(TextSpan(str))

    def slog(self, str):
        self.array[self.pos - self.start] = str
        self.pos = self.pos + 1
        if self.pos - self.start >= self.threshold:
            self.start = self.start + self.threshold
        self.detect = self.detect + 1
        for n in self.log_notify:
            n.log(self, str)

reloadable.register_for_reload(Buffer)

## End. ##
