##
## window.py -- Display window with associated storage.
##
## Copyleft 1997 Teemu Kalvas <chery@s2.org>
##

## +class Window       (screen,  screen on which to draw
##                      next,    next window initializer
##                      prev,    previous window initializer
##                      name,    name initializer
##                      server)  server initializer
##  -method page_up    ()
##  -method page_down  ()
##  -method set_name   (name)    new window name
##  -method log        (str)     string to log
##  -method redraw     ()
##  -method next
##  -method prev
##  -method name
##  -method server

import curses
import string

import linelist

import config

def nwrap(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 nwlen(line, width):
    return len(wrap(line, width))

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

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

def wrap(line, width):
    if config.emacs_wrap:
        return owrap(line, width)
    else:
        return nwrap(line, width)

def wlen(line, width):
    if config.emacs_wrap:
        return owlen(line, width)
    else:
        return nwlen(line, width)

drawline_trans = string.maketrans('\000\001\002\003\004\005\006\007\010\011' +
				  '\012\013\014\015\016\017\020\021\022\023' +
				  '\024\025\026\027\030\031\032\033\034\035' +
				  '\036\037\200\201\202\203\204\205\206\207' +
				  '\210\211\212\213\214\215\216\217\220\221' +
				  '\222\223\224\225\226\227\230\231\232\233' +
				  '\234\235\236\237', '____________________' +
				  '________________________________________' +
				  '____')

def drawline(window, y, line):
    window.addstr(y, 0, string.translate(line, drawline_trans))

class Window:
    def __init__(self, screen, next, prev, name, server):
	self.screen = screen
	self.next = next
	self.prev = prev
	self.name = name
	self.server = server
	## at is actually the (line, part) of the first line off the bottom of
	## the display area.  Thus it is always greater than or equal to (0, 0)
	## and less than or equal to (lines.lines, 0).
	self.at = 0, 0
	self.lines = linelist.LineList(8)
	self.hold = 0
	self.detect = 0
	screen.touched = screen.touched | 8

    def page_up(self):
	height, width = self.screen.log_area.getmaxyx()
	i = height - 1
	while i:
	    if self.at[1] > 0:
		self.at = self.at[0], self.at[1] - 1
	    elif self.at[0] > 0:
		self.at = (self.at[0] - 1,
			   wlen(self.lines.lookup(self.at[0] - 1), width) - 1)
	    else:
		break
	    if self.at[0] < self.lines.lines:
		self.hold = 1
	    i = i - 1
	self.screen.touched = self.screen.touched | 8

    def page_down(self):
	height, width = self.screen.log_area.getmaxyx()
	i = height - 1
	l = wlen(self.lines.lookup(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] < self.lines.lines:
		self.at = self.at[0] + 1, 0
		if self.at[0] == self.lines.lines:
		    self.hold = 0
		    break
		l = wlen(self.lines.lookup(self.at[0]), width)
	    else:
		## This should never be reached.
		break
	    i = i - 1
	self.screen.touched = self.screen.touched | 8

    def set_name(self, name):
	self.name = name
	self.screen.touched = self.screen.touched | 16

    def log_lines(self, head, str):
        for s in string.split(str, '\n'):
            if s:
                self.log(head + s)

    def log(self, str):
	visible = self == self.screen.current
	window = self.screen.log_area
	height, width = window.getmaxyx()
	wrapped = wrap(str, width)
	self.lines.append(str)
	if not self.hold:
	    self.at = self.at[0] + 1, 0
	    if visible:
                #window.scrollok(1)
                pfll = 0
		for line in wrapped:
                    if not pfll:
                        window.scroll()
		    drawline(window, height - 1, line)
                    if len(line) == width:
                        pfll = 1
                    #window.move(height - 1, 0)
		    ##window.insstr(height - 1, 0, line)
                #window.scrollok(0)
		self.screen.touched = self.screen.touched | 1
	if not visible:
	    self.detect = self.detect + 1
	    self.screen.touched = self.screen.touched | 16

    def redraw(self):
	window = self.screen.log_area
	height, width = window.getmaxyx()
	window.clear()
	y, i, j = height - 1, self.at[0], self.at[1]
	if j > 0:
	    wrapped = wrap(self.lines.lookup(i), width)
	while y >= 0:
	    j = j - 1
	    if j < 0:
		i = i - 1
		if i < 0:
		    self.screen.touched = self.screen.touched | 1
		    return
		wrapped = wrap(self.lines.lookup(i), width)
		j = len(wrapped) - 1
            if y == height - 1 and len(wrapped[j]) == width:
                window.addstr(y, 0, string.translate(wrapped[j][:width - 2]
                                                     + wrapped[j][width - 1],
                                                     drawline_trans))
                window.insch(y, width - 2, ord(
                    string.translate(wrapped[j][width - 2], drawline_trans)))
            else:
                drawline(window, y, wrapped[j])
	    ##window.insstr(y, 0, wrapped[j])
	    y = y - 1
	self.screen.touched = self.screen.touched | 1

## End. ##
