#!/usr/bin/env python/ import sys import string import time import struct import curses import curses.ascii import curses.wrapper INPUT_TIMEOUT= 10 STORED_SCREENS= 2 class MyWin: def __init__( self, rows, cols, y, x ): self.y= y self.x= x self.rows= rows self.cols= cols self.w= curses.newwin( rows, cols, y, x ) #self.w.bkgdset( 0, curses.COLOR_YELLOW ) self.w.scrollok(1) def resize( self, sizeY, sizeX, y, x ): self.w= curses.newwin( sizeY, sizeX, y, x ) self.x= x self.y= y self.rows= sizeY self.cols= sizeX self.w.scrollok(1) def addch( self, char ): self.w.addch( char ) def addstr( self, text, attr= None ): if attr: self.w.addstr( text, attr ) else: self.w.addstr( text ) def erase( self ): self.w.erase() def refresh( self ): self.w.refresh() class MyScrollWin(MyWin): def __init__( self, rows, cols, y, x ): MyWin.__init__( self, rows, cols, y, x ) self.pRows= rows * STORED_SCREENS self.p= curses.newpad( self.pRows, cols ) self.p.scrollok(1) self.scroll= 0 self.text= [] def addch( self, char ): self.p.addch( char ) def addstr( self, text, attr= None ): self.text.append( (text, attr) ) #print >>sys.stderr, 'paso' try: if attr: self.p.addstr( text, attr ) else: self.p.addstr( text ) except curses.error, e: #print >>sys.stderr, 'UOP', e pass (padY, padX)= self.p.getyx() (scrY, scrX)= self.p.getmaxyx() #print >>sys.stderr, 'pady= ', padY #print >>sys.stderr, 'scrY= ', scrY if padY >= (scrY - 1): self.pRows*= 2 self.p= curses.newpad( self.pRows, scrX ) self.redraw() def dump( self, file ): for elem in self.text: file.write( elem[0] ) file.close() def resize( self, sizeY, sizeX, y, x ): #print >>sys.stderr, 'newpad: sizeY= %d, sizeX= %d' % ( sizeY * STORED_SCREENS, sizeX ) #print >>sys.stderr, 'resizePad: sizeY= %d, sizeX= %d' % ( sizeY, sizeX ) self.p= curses.newpad( self.pRows, sizeX ) self.x= x self.y= y self.rows= sizeY self.cols= sizeX #print >>sys.stderr, 'text=', self.text self.redraw() def refresh( self ): (y, x)= self.p.getyx() firstRow= y - (self.rows - 1) if (firstRow + self.scroll) < 0: firstRow= 0 #print >>sys.stderr, str(self), firstRow + self.scroll, self.x, self.y, self.x , self.y+self.rows-1, self.cols-1 #(scrY, scrX)= curses.getmaxyx() #rows= self.rows #cols= self.cols #if scrY < rows: #rows= scrY #if scrX < cols: #cols= scrX #print >>sys.stderr, 'prefresh: pminrow= %d, pmincol= %d, sminrow= %d, smincol= %d, smaxrow= %d, smaxcol= %d' % \ #(firstRow + self.scroll, 0, self.y, 0 \ #, self.y+self.rows-1, self.cols-1) #print >>sys.stderr, 'self.y= %d' % (self.y) #print >>sys.stderr, 'self.rows= %d' % (self.rows) sizeY= self.y+self.rows-1 (padY, padX)= self.p.getyx() #print >>sys.stderr, 'sizeY= %d, padY= %d' % (sizeY, padY) try: self.p.refresh(firstRow + self.scroll, 0, self.y, 0 , self.y+self.rows-1, self.cols-1) except curses.error: pass #self.p.refresh(firstRow + self.scroll, self.x, self.y, self.x #, self.y+self.rows-1, self.cols-1) def redraw( self ): self.p.erase() for elem in self.text: #print >>sys.stderr, 'elem=', elem if elem[1] == None: self.p.addstr( elem[0] ) else: self.p.addstr( elem[0], elem[1] ) def attrset( self, color ): self.p.attrset( color ) def toTop( self ): (y, x)= self.p.getyx() self.scroll= -(y - self.rows +1) def toBottom( self ): self.scroll= 0 def line( self ): (y, x)= self.p.getyx() (maxY, maxX)= self.p.getmaxyx() #print >>sys.stderr, '%d %d - ' % (x, y) #print >>sys.stderr, '%d %d' % (maxX, maxY) self.p.hline( y, x, curses.ACS_HLINE, maxX - x ) def scrollUp( self, lines= 1 ): (y, x)= self.p.getyx() firstRow= y - self.rows if (firstRow + self.scroll - lines ) >= 0: self.scroll-= lines else: self.scroll= -(y - self.rows +1) self.refresh() def getWin( self ): return self.w def erase( self ): self.text= [] self.p.erase() #self.refresh() def scrollDown( self, lines= 1 ): (y, x)= self.p.getyx() if (self.scroll + lines) < 0: self.scroll+= lines else: self.scroll= 0 self.refresh() class MyInputWin(MyScrollWin): def __init__( self, rows, cols, y, x ): MyScrollWin.__init__( self, rows, cols, y, x ) self.p.timeout( INPUT_TIMEOUT ) self.p.keypad(1) self.attr= None #print >>sys.stderr, str(self), self.rows, self.cols, self.y, self.x self.hidden= 0 def setAttr( self, attr ): self.attr= attr def resize( self, sizeY, sizeX, y, x ): MyScrollWin.resize( self, sizeY, sizeX, y, x ) self.p.timeout( INPUT_TIMEOUT ) self.p.keypad(1) def getLine( self, handleFunc= None, idleFunc= None, hidden= 0 ): #curses.noecho() self.p.immedok(0) #l= open('/tmp/jeje', 'w') self.buff= '' self.pos= 0 self.hidden= hidden while 1: c= self.p.getch() #l.write( str(c) ) #print >>sys.stderr, 'leido= %s\n' % str(c) if c == curses.ascii.NL: break elif c != curses.ERR: #print >>sys.stderr, 'en el elif' if not handleFunc( c ): #print >>sys.stderr, 'en if' if self.pos < len(self.buff): self.buff= self.buff[:self.pos] + chr(c) \ + self.buff[self.pos:] self.erase() #print >>sys.stderr, 'lala= %s' % self.buff if not self.hidden: #print >>sys.stderr, 'en if2' if self.attr: self.p.addstr( self.buff, self.attr ) else: self.p.addstr( self.buff ) self.cursPos(self.pos+1) self.refresh() else: self.buff+= chr(c) if not self.hidden: #print >>sys.stderr, 'self.attr' if self.attr: self.p.addch( c, self.attr ) else: self.p.addch( c ) #print >>sys.stderr, 'getLine=', self.p.getyx() self.refresh() self.pos += 1 else: if idleFunc != None: idleFunc() else: curses.napms( 1 ) self.hidden= 0 return self.buff #def refresh( self ): #(y, x)= self.p.getyx() #firstRow= y - self.rows #if (firstRow + self.scroll) < 0: #firstRow= 0 #print >>sys.stderr, firstRow + self.scroll, 0, self.y, self.x, self.y+self.rows-1, self.cols-1 #self.p.refresh(firstRow + self.scroll, 0, self.y+1, self.x, self.rows-1 #, self.cols-1) #self.p.refresh(0, 0, 23, 0, 24, 79) def delChar( self ): if self.pos >= 1: self.pos-= 1 self.buff= self.buff[:self.pos] + self.buff[self.pos+1:] if not self.hidden: self.p.erase() if self.attr: self.p.addstr( self.buff, self.attr ) else: self.p.addstr( self.buff ) self.cursPos( self.pos ) def suprChar( self ): self.buff= self.buff[:self.pos] + self.buff[self.pos+1:] if not self.hidden: self.p.erase() if self.attr: self.p.addstr( self.buff, self.attr ) else: self.p.addstr( self.buff ) self.cursPos( self.pos ) def cursPos( self, pos ): y= pos/self.cols x= pos%self.cols #print >>sys.stderr, 'cursor=', self.p.getyx() self.p.move( y, x ) if y >= self.rows: y= self.rows - 1 #print >>sys.stderr, '/= %d, %%=%d' % (pos/self.cols, pos%self.cols) #print >>sys.stderr, 'move=', y, x self.w.move( y, x ) def cursBegin( self ): self.pos= 0 self.cursPos( self.pos ) def cursEnd( self ): self.pos= len( self.buff ) self.cursPos( self.pos ) def cursBack( self ): if self.pos >= 1: self.pos-= 1 self.cursPos( self.pos ) def cursForward( self ): if self.pos < len(self.buff): self.pos+= 1 self.cursPos( self.pos ) def addstr( self, text ): self.buff= text self.pos= len( text ) self.p.addstr( text ) class MyWinStack: def __init__( self, rows, cols, y, x ): self.y= y self.x= x self.rows= rows self.cols= cols #w= MyScrollWin( rows, cols, y, x ) self.wins= {} def resize( self, sizeY, sizeX, y, x ): self.y= y self.x= x self.rows= sizeY self.cols= sizeX for win in self.wins.values(): win.resize( sizeY, sizeX, y, x ) def dump( self, chat, file ): self.wins[chat].dump( file ) def newWin( self, chat ): w= MyScrollWin( self.rows, self.cols, self.y, self.x ) self.wins[chat]= w def replaceChat( oldChat, newChat ): self.wins[newChat]= self.wins[oldChat] del( self.wins[oldChat] ) def hasWin( self, chat ): return self.wins.has_key( chat ) def show( self, chat ): w= self.wins[chat] w.refresh() def delWin( self, chat ): del( self.wins[chat] ); def erase( self, chat ): self.wins[chat].erase() def addstr( self, chat, text, attr= None ): if self.wins.has_key( chat ): w= self.wins[chat] try: w.addstr( text, attr ) except curses.error: self.addstr( None, _('Detected ERROR when displaying: ') + text ) def scrollUp( self, chat, lines= 1 ): w= self.wins[chat] w.scrollUp( lines ) def scrollDown( self, chat, lines= 1 ): w= self.wins[chat] w.scrollDown( lines ) def toTop( self, chat ): self.wins[chat].toTop() def toBottom( self, chat ): self.wins[chat].toBottom() def redraw( self ): for w in self.wins.values(): w.redraw() def refresh( self, chat ): w= self.wins[chat] w.refresh() def dummy( c ): return 1 def main(a): #curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) #curses.meta(1) v1= MyWin( 22, 80, 0, 0 ) v2= MyInputWin(2, 80, 22, 0) #v1.hline(21, 0, curses.ACS_HLINE, 80) #p1.refresh(0, 0, 0, 0, 22, 80) #p2.refresh(0, 0, 22, 0, 24, 80) v1.refresh() v2.refresh() while 1: st= v2.getLine( dummy, hidden= 1 ) v1.addstr( st ) v1.refresh() #p1.refresh(0, 0, 0, 0, 22, 80) #p2.refresh(0, 0, 22, 0, 24, 80) #raw_input() if __name__ == '__main__': curses.wrapper(main)