##
## clirc -- An IRC client in Python.
## curseswindow.py - Curses buffer displayer.
##
## Copyleft 1997-2000 Teemu Kalvas <chery@s2.org>
##

import curses

import buffer
import config
import main
import reloadable

def new_wrap(line, width):
    w23 = 2 * width / 3
    wrapped = []
    pt = 0
    i = 0
    last = 0
    l = len(line) - width
    while last < l:
        if line[i] == ' ':
            pt = i
        if i - last >= width:
            if pt > last + w23:
                wrapped.append(line[last:pt])
                last = pt + 1
            else:
                wrapped.append(line[last:last + width - 1] + '\\')
                last = last + width - 1
            pt = 0
        else:
            i = i + 1
    wrapped.append(line[last:])
    return wrapped

def new_wlen(line, width):
    return len(new_wrap(line, width))

def old_wrap(line, width):
    wrapped = []
    while len(line) >= width:
        wrapped.append(line[:width -1 ] + '\\')
        line = line[width - 1:]
    wrapped.append(line)
    return wrapped

def old_wlen(line, width):
    return (len(line) + width - 2) / (width - 1)

def wrap(line, width):
    if config.emacs_wrap:
        return old_wrap(line, width)
    else:
        return new_wrap(line, width)

def wlen(line, width):
    if config.emacs_wrap:
        return old_wlen(line, width)
    else:
        return new_wlen(line, width)

class CursesWindow(reloadable.Reloadable):
    def __init__(self, name, buf, screen):
        self.name = name
        self.buf = buf
        self.screen = screen
        self.hold = 0
        self.at = 0, 0
        self.detect = 0
        buf.register(self)
        self.changed()

    def window(self):
        return self.screen.get_window(self)

    def log(self, buffer, str):
        if not self.hold:
            self.at = self.at[0] + 1, 0
            window = self.window()
            if window:
                height, width = window.getmaxyx()
		self.w = window
                wrapped = wrap(str, width)
                for line in wrapped:
                    window.scroll()
                    line.print_line(self.print_span, height - 1)
                self.changed()
		del self.w
            else:
                self.detect = self.detect + 1
                main.status_change()

    def page_down(self):
        height, width = self.window().getmaxyx()
        i = height - 1
        l = wlen(self.buf[self.at[0]], width) - self.at[1]
        while i:
            if self.at[1] < l - 1:
                self.at = self.at[0], self.at[1] + 1
            elif self.at[0] < len(self.buf):
                self.at = self.at[0] + 1, 0
                if self.at[0] == len(self.buf):
                    self.hold = 0
                    break
                l = wlen(self.buf[self.at[0]], width)
            else:
                ## Never reached, but just to make sure.
                break
            i = i - 1
        self.redraw()

    def page_up(self):
        height, width = self.window().getmaxyx()
        i = height - 1
        while i:
            if self.at[1] > 0:
                self.at = self.at[0], self.at[1] - 1
            elif self.at[0] > self.buf.log_start():
                self.at = self.at[0] - 1, wlen(
                    self.buf[self.at[0] - 1], width) - 1
            else:
                break
            if self.at[0] < len(self.buf):
                self.hold = 1
            i = i - 1
        self.redraw()

    def pre_delete(self):
        self.buf.unregister(self)
        self.screen.remove_window(self)

    def changed(self):
        self.screen.window_changed(self)

    def redraw(self):
        self.detect = 0
        self.screen.redraw_window(self)

    def print_span(self, y, x, str, attr):
	if str:
	    cattr = 0
	    if attr & 1:
		cattr = cattr ^ curses.A_BOLD
	    if attr & 2:
		cattr = cattr ^ curses.A_UNDERLINE
	    if attr & 4:
		cattr = cattr ^ curses.A_REVERSE
	    ll = len(str)
	    if ll > 1:
		self.w.addstr(y, x, str[:-1], cattr)
	    self.w.insch(y, x + ll - 1, ord(str[-1]), cattr)

    def redraw_event(self):
	window = self.window()
	if not window:
	    ## If two change window -keystrokes are queued before they can be
	    ## handled, there will be redraw_events queued for both of them
	    ## before the redraws actually take place, and only one of them
	    ## will have a valid window.
	    return
	height, width = window.getmaxyx()
	self.w = window
	window.clear()
	y, i, j = height - 1, self.at[0], self.at[1]
	if j > 0:
	    wrapped = wrap(self.buf[i], width)
	while y >= 0:
	    j = j - 1
	    if j < 0:
		i = i - 1
		if i < 0:
                    break
		wrapped = wrap(self.buf[i], width)
		j = len(wrapped) - 1
            wrapped[j].print_line(self.print_span, y)
	    y = y - 1
        self.changed()
	del self.w

reloadable.register_for_reload(CursesWindow)

## End. ##
