2020-06-28 15:27:56 +00:00
|
|
|
# This file is part of MarMOTS.
|
|
|
|
#
|
|
|
|
# MarMOTS is free software: you can redistribute it and/or modify it under the terms of the GNU Affero
|
|
|
|
# General Public License as published by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# MarMOTS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
|
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
|
|
|
|
# Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License along with MarMOTS. If not,
|
|
|
|
# see <https://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
# Copyright 2009, 2010, 2011, 2020 Jeremy Penner
|
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
import config
|
|
|
|
|
|
|
|
cdef extern from "stdio.h":
|
|
|
|
int sprintf(char *, char *,...)
|
|
|
|
|
|
|
|
cdef extern from "stdlib.h":
|
|
|
|
ctypedef unsigned long size_t
|
|
|
|
void free(void *ptr)
|
|
|
|
void *malloc(size_t size)
|
|
|
|
void *calloc(size_t nelem, size_t elsize)
|
|
|
|
void *realloc(void *ptr, size_t size)
|
|
|
|
size_t strlen(char *s)
|
|
|
|
char *strcpy(char *dest, char *src)
|
|
|
|
|
|
|
|
esc = '%s['%chr(27)
|
|
|
|
reset = '%s0m'%esc
|
|
|
|
cls = '%s2j'%esc
|
|
|
|
|
|
|
|
BLACK = 0
|
|
|
|
RED = 1
|
|
|
|
GREEN = 2
|
|
|
|
YELLOW = 3
|
|
|
|
BLUE = 4
|
|
|
|
MAGENTA = 5
|
|
|
|
CYAN = 6
|
|
|
|
WHITE = 7
|
|
|
|
|
|
|
|
FBRIGHT = 8
|
|
|
|
FBLINK = 16
|
|
|
|
|
|
|
|
rgcolorBg = range(8)
|
|
|
|
rgcolorFg = range(8)
|
|
|
|
rgcolorFg.extend([col | FBRIGHT for col in range(8)])
|
|
|
|
|
|
|
|
K_BACKSPACE = chr(8)
|
|
|
|
K_TAB = chr(9)
|
|
|
|
K_RETURN = chr(10)
|
2020-06-27 19:39:10 +00:00
|
|
|
K_NEWLINE = chr(13)
|
2011-03-19 00:10:02 +00:00
|
|
|
K_DEL = chr(127)
|
|
|
|
K_LEFT = 256
|
|
|
|
K_RIGHT = 257
|
|
|
|
K_UP = 258
|
|
|
|
K_DOWN = 259
|
|
|
|
K_HOME = 260
|
|
|
|
K_END = 261
|
|
|
|
K_PGUP = 262
|
|
|
|
K_PGDN = 263
|
|
|
|
|
|
|
|
def StrKey(ch):
|
|
|
|
if type(ch) == str:
|
|
|
|
return ord(ch)
|
|
|
|
return str(ch)
|
|
|
|
|
|
|
|
def Ctrl(ch):
|
|
|
|
ch = ch.upper()
|
|
|
|
assert ch != 'M' and ch != 'J' and ch != 'H'
|
|
|
|
return chr(ord(ch - 'A' + 1))
|
|
|
|
|
|
|
|
def FEnter(key):
|
|
|
|
return key == "\n" or key == "\r"
|
|
|
|
|
|
|
|
cdef struct SAch:
|
|
|
|
unsigned char ch
|
|
|
|
char fgCol
|
|
|
|
char bgCol
|
|
|
|
|
|
|
|
cdef union UAch:
|
|
|
|
int ach
|
|
|
|
SAch sach
|
|
|
|
|
|
|
|
cpdef MkAch(char *ch, char fgcol=WHITE, char bgcol=BLACK):
|
|
|
|
cdef UAch uach
|
|
|
|
uach.sach.ch = ch[0]
|
|
|
|
uach.sach.fgCol = fgcol
|
|
|
|
uach.sach.bgCol = bgcol
|
|
|
|
return uach.ach
|
|
|
|
|
|
|
|
# the class must be named Ach for backwards compatibility, but the hungarian name is OAch
|
|
|
|
class Ach(object):
|
|
|
|
def __init__(self, int ach):
|
|
|
|
cdef UAch uach
|
|
|
|
uach.ach = ach
|
|
|
|
self.ch = chr(uach.sach.ch)
|
|
|
|
self.fgCol = uach.sach.fgCol
|
|
|
|
self.bgCol = uach.sach.bgCol
|
|
|
|
|
|
|
|
def ToAch(self):
|
|
|
|
return MkAch(self.ch, self.fgCol, self.bgCol)
|
|
|
|
|
|
|
|
cdef AchFromOach(oach):
|
|
|
|
if oach == None:
|
|
|
|
return achBlankI
|
|
|
|
return MkAch(oach.ch, oach.fgCol, oach.bgCol)
|
|
|
|
cdef OachFromAch(int ach):
|
|
|
|
if ach == achBlankI:
|
|
|
|
return None
|
|
|
|
assert ach != achInvdI
|
|
|
|
return Ach(ach)
|
|
|
|
|
|
|
|
def ChFromAch(int ach):
|
|
|
|
cdef UAch uach
|
|
|
|
uach.ach = ach
|
|
|
|
return chr(uach.sach.ch)
|
|
|
|
|
|
|
|
achBlank = 0
|
|
|
|
achInvd = -1
|
|
|
|
|
|
|
|
cdef enum:
|
|
|
|
achBlankI = 0
|
|
|
|
achInvdI = -1
|
|
|
|
chesc = 27
|
|
|
|
FBRIGHTI = 8
|
|
|
|
FBLINKI = 16
|
|
|
|
|
2020-06-28 03:03:24 +00:00
|
|
|
cdef AstFromAch(int ach, int achPrev = achInvdI):
|
2011-03-19 00:10:02 +00:00
|
|
|
cdef UAch uach, uachPrev
|
|
|
|
uach.ach = ach
|
|
|
|
uachPrev.ach = achPrev
|
|
|
|
cdef char ast[60]
|
|
|
|
cdef char sgr[4]
|
|
|
|
cdef int csgr = 0
|
|
|
|
|
|
|
|
if (achPrev == achInvdI) or (uachPrev.sach.fgCol != uach.sach.fgCol):
|
|
|
|
fBright = uach.sach.fgCol & FBRIGHTI
|
2020-06-28 03:03:24 +00:00
|
|
|
if (achPrev == achInvdI) or (fBright != (uachPrev.sach.fgCol & FBRIGHTI)):
|
2011-03-19 00:10:02 +00:00
|
|
|
if fBright:
|
|
|
|
sgr[csgr] = 1
|
|
|
|
else:
|
2020-06-28 03:03:24 +00:00
|
|
|
sgr[csgr] = 0
|
|
|
|
achPrev = achInvdI
|
2011-03-19 00:10:02 +00:00
|
|
|
csgr = csgr + 1
|
2020-06-28 03:03:24 +00:00
|
|
|
sgr[csgr] = (uach.sach.fgCol & 7) + 30
|
|
|
|
csgr = csgr + 1
|
|
|
|
# fBlink = uach.sach.fgCol & FBLINKI
|
|
|
|
# if (achPrev == achInvdI) or (fBlink != uachPrev.sach.fgCol & FBLINKI):
|
|
|
|
# if fBlink:
|
|
|
|
# sgr[csgr] = 5
|
|
|
|
# else:
|
|
|
|
# sgr[csgr] = 25
|
|
|
|
# csgr = csgr + 1
|
2011-03-19 00:10:02 +00:00
|
|
|
if (achPrev == achInvdI) or (uachPrev.sach.bgCol != uach.sach.bgCol):
|
|
|
|
sgr[csgr] = uach.sach.bgCol + 40
|
|
|
|
csgr = csgr + 1
|
|
|
|
if csgr == 0:
|
|
|
|
sprintf(ast, "%c", uach.sach.ch)
|
|
|
|
elif csgr == 1:
|
|
|
|
sprintf(ast, "%c[%dm%c", chesc, sgr[0], uach.sach.ch)
|
|
|
|
elif csgr == 2:
|
|
|
|
sprintf(ast, "%c[%d;%dm%c", chesc, sgr[0], sgr[1], uach.sach.ch)
|
|
|
|
elif csgr == 3:
|
|
|
|
sprintf(ast, "%c[%d;%d;%dm%c", chesc, sgr[0], sgr[1], sgr[2], uach.sach.ch)
|
|
|
|
elif csgr == 4:
|
|
|
|
sprintf(ast, "%c[%d;%d;%d;%dm%c", chesc, sgr[0], sgr[1], sgr[2], sgr[3], uach.sach.ch)
|
|
|
|
else:
|
|
|
|
assert csgr >= 0 and csgr <= 4, "more sgr possibilities, please handle"
|
|
|
|
return ast
|
|
|
|
|
|
|
|
mpch_entity = [0, 9786, 9787, 9829, 9830, 9827, 9824, 8226, 9688, 9675, 9689, 9794, 9792, 9834, 9835, 9788, 9658, 9668, 8597, 8252,
|
|
|
|
182, 167, 9644, 8616, 8593, 8595, 8594, 8592, 8735, 8596, 9650, 9660, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
|
|
|
|
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
|
|
|
|
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
|
|
|
|
103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
|
|
|
|
8962, 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242, 251,
|
|
|
|
249, 255, 214, 220, 162, 163, 165, 8359, 402, 225, 237, 243, 250, 241, 209, 170, 186, 191, 8976, 172, 189, 188, 161, 171,
|
|
|
|
187, 9617, 9618, 9619, 9474, 9508, 9569, 9570, 9558, 9557, 9571, 9553, 9559, 9565, 9564, 9563, 9488, 9492, 9524, 9516,
|
|
|
|
9500, 9472, 9532, 9566, 9567, 9562, 9556, 9577, 9574, 9568, 9552, 9580, 9575, 9576, 9572, 9573, 9561, 9560, 9554, 9555,
|
|
|
|
9579, 9578, 9496, 9484, 9608, 9604, 9612, 9616, 9600, 945, 223, 915, 960, 931, 963, 181, 964, 934, 920, 937, 948, 8734,
|
|
|
|
966, 949, 8745, 8801, 177, 8805, 8804, 8992, 8993, 247, 8776, 176, 8729, 183, 8730, 8319, 178, 9632, 160]
|
|
|
|
|
|
|
|
setch_unsafe = set([ord('&'), ord('<'), ord('>'), ord('"'), ord("'")])
|
|
|
|
mpcol_hcol = ["#000000", "#AA0000", "#00AA00", "#AA5500", "#0000AA", "#AA00AA", "#00AAAA", "#AAAAAA",
|
|
|
|
"#555555", "#FF5555", "#55FF55", "#FFFF55", "#5555FF", "#FF55FF", "#55FFFF", "#FFFFFF"]
|
|
|
|
|
|
|
|
cdef HstFromAch(int ach, int achPrev = achInvdI):
|
|
|
|
cdef UAch uach, uachPrev
|
|
|
|
uach.ach = ach
|
|
|
|
uachPrev.ach = achPrev
|
|
|
|
stStyle = None
|
|
|
|
if achPrev == achInvdI or uachPrev.sach.fgCol != uach.sach.fgCol or uachPrev.sach.bgCol != uach.sach.bgCol:
|
|
|
|
stStyle = "color:" + mpcol_hcol[uach.sach.fgCol & 15] + ";background-color:" + mpcol_hcol[uach.sach.bgCol & 15]
|
|
|
|
rgst = []
|
|
|
|
if stStyle != None and achPrev != achInvdI:
|
|
|
|
rgst.append("</span>")
|
|
|
|
if stStyle != None:
|
|
|
|
rgst.append("<span style='" + stStyle + "'>")
|
|
|
|
if ach == achBlank:
|
|
|
|
rgst.append(' ')
|
|
|
|
else:
|
|
|
|
entity = mpch_entity[uach.sach.ch]
|
|
|
|
if entity == uach.sach.ch and not uach.sach.ch in setch_unsafe:
|
|
|
|
rgst.append(chr(uach.sach.ch))
|
|
|
|
else:
|
|
|
|
rgst.append("&#" + str(entity) + ";")
|
|
|
|
return ''.join(rgst)
|
|
|
|
|
|
|
|
class Pos(object):
|
|
|
|
def __init__(self, int w=config.W, int h=config.H, int x=1, int y=1):
|
|
|
|
self.i = PosI(w, h, x, y)
|
|
|
|
def X(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.X()
|
|
|
|
def Y(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.Y()
|
2011-10-05 21:45:36 +00:00
|
|
|
def Xz(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.xz
|
|
|
|
def Yz(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.yz
|
2011-03-19 00:10:02 +00:00
|
|
|
def Inc(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
posI.Inc()
|
|
|
|
def Up(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.Up()
|
|
|
|
def Down(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.Down()
|
|
|
|
def Left(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.Left()
|
|
|
|
def Right(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.Right()
|
2020-07-31 03:01:02 +00:00
|
|
|
def Clone(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return posI.ToPos()
|
|
|
|
def Equals(self, other):
|
|
|
|
cdef PosI posIL = self.i
|
|
|
|
cdef PosI posIR = other.i
|
|
|
|
return posIL.xz == posIR.xz and posIL.yz == posIR.yz and posIL.w == posIR.w and posIL.h == posIR.h
|
2011-03-19 00:10:02 +00:00
|
|
|
def __setstate__(self, state):
|
|
|
|
self.i = PosI(state["w"], state["h"], state["xz"] + 1, state["yz"] + 1)
|
|
|
|
def __getstate__(self):
|
|
|
|
cdef PosI posI = self.i
|
|
|
|
return {"w": posI.w, "h": posI.h, "xz": posI.xz, "yz": posI.yz}
|
|
|
|
|
|
|
|
cdef class PosI(object):
|
|
|
|
cdef int w, h, xz, yz
|
|
|
|
def __init__(self, int w=config.W, int h=config.H, int x=1, int y=1):
|
|
|
|
self.w = w
|
|
|
|
self.h = h
|
|
|
|
self.xz = x - 1
|
|
|
|
self.yz = y - 1
|
|
|
|
|
|
|
|
cdef inline X(self): return self.xz + 1
|
|
|
|
cdef inline Y(self): return self.yz + 1
|
|
|
|
|
|
|
|
cdef inline Inc(self):
|
|
|
|
if self.xz == self.w - 1:
|
|
|
|
if self.yz < self.h:
|
|
|
|
self.xz = 0
|
|
|
|
self.yz = self.yz + 1
|
|
|
|
else:
|
|
|
|
self.xz = self.xz + 1
|
|
|
|
|
|
|
|
cdef inline Up(self):
|
|
|
|
if self.yz > 0:
|
|
|
|
self.yz = self.yz - 1
|
|
|
|
return True
|
|
|
|
cdef inline Down(self):
|
|
|
|
if self.yz < self.h - 1:
|
|
|
|
self.yz = self.yz + 1
|
|
|
|
return True
|
|
|
|
cdef inline Left(self):
|
|
|
|
if self.xz > 0:
|
|
|
|
self.xz = self.xz - 1
|
|
|
|
return True
|
|
|
|
cdef inline Right(self):
|
|
|
|
if self.xz < self.w - 1:
|
|
|
|
self.xz = self.xz + 1
|
|
|
|
return True
|
|
|
|
cdef ToPos(self):
|
|
|
|
return Pos(self.w, self.h, self.X(), self.Y())
|
|
|
|
|
|
|
|
class Ascr(object):
|
|
|
|
def __init__(self, int w=config.W, int h=config.H, int achFill = achBlankI):
|
|
|
|
cdef AscrI ascrI = AscrI(w,h)
|
|
|
|
self.i = ascrI
|
|
|
|
if achFill != achBlankI:
|
|
|
|
ascrI.Fill(achFill, w, h)
|
|
|
|
|
|
|
|
def __setstate__(self, state):
|
|
|
|
cdef AscrI ascrI = AscrI(state["w"], state["h"])
|
|
|
|
self.i = ascrI
|
|
|
|
cdef int iach = 0
|
|
|
|
for mpxz_oach in state["mpyzxz_ach"]:
|
|
|
|
for oach in mpxz_oach:
|
|
|
|
ascrI.rgach[iach] = AchFromOach(oach)
|
|
|
|
iach = iach + 1
|
|
|
|
|
|
|
|
def __getstate__(self):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
cdef int iach = 0
|
|
|
|
mpyzxz_oach = []
|
|
|
|
for yz in range(ascrI.h):
|
|
|
|
mpxz_oach = []
|
|
|
|
for xz in range(ascrI.w):
|
|
|
|
mpxz_oach.append(OachFromAch(ascrI.rgach[iach]))
|
|
|
|
iach = iach + 1
|
|
|
|
mpyzxz_oach.append(mpxz_oach)
|
|
|
|
return {"w":ascrI.w, "h":ascrI.h, "mpyzxz_ach": mpyzxz_oach}
|
|
|
|
|
|
|
|
def W(self):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.w
|
|
|
|
def H(self):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.h
|
|
|
|
def ZPos(self, int xz, int yz):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.ZPos(xz, yz)
|
|
|
|
|
|
|
|
def PutAch(self, int ach, int x, int y):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
ascrI.PutAch(ach, x, y)
|
|
|
|
|
|
|
|
def GetAch(self, int x, int y):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.rgach[ascrI.IAch(x - 1, y - 1)]
|
|
|
|
|
|
|
|
def PutRgach(self, rgach, int x, int y):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
ascrI.PutRgach(rgach, x, y)
|
|
|
|
|
|
|
|
def PutSt(self, char *st, int x, int y, int colFg = WHITE, int colBg=BLACK):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
ascrI.PutSt(st, x, y, colFg, colBg)
|
|
|
|
|
|
|
|
def Fill(self, int ach, int wIn, int hIn, int x = 1, int y = 1):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
ascrI.Fill(ach, wIn, hIn, x, y)
|
|
|
|
|
|
|
|
def PutAscr(self, ascr, int x=1, int y=1):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
ascrI.PutAscr(ascr.i, x, y)
|
2011-04-12 15:37:52 +00:00
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
def AstDiff(self, ascr):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.AstDiff(ascr.i)
|
|
|
|
|
|
|
|
def Hst(self):
|
|
|
|
cdef AscrI ascrI = self.i
|
|
|
|
return ascrI.Hst()
|
2011-04-12 15:37:52 +00:00
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
def Ast(self):
|
|
|
|
return Ascr(self.W(), self.H(), achInvdI).AstDiff(self) #stupid implementation
|
|
|
|
|
|
|
|
# ANSI Screen
|
|
|
|
cdef class AscrI(object):
|
|
|
|
cdef int w, h
|
|
|
|
cdef int *rgach
|
|
|
|
def __cinit__(self, int w=config.W, int h=config.H, int achFill = achBlankI):
|
|
|
|
self.rgach = <int*>calloc(w * h, sizeof(int))
|
|
|
|
if achFill != achBlankI:
|
|
|
|
for iach in range(w * h):
|
|
|
|
self.rgach[iach] = achFill
|
|
|
|
self.w = w
|
|
|
|
self.h = h
|
|
|
|
|
|
|
|
def __dealloc__(self):
|
|
|
|
free(self.rgach)
|
|
|
|
|
|
|
|
cdef Zpos(self, int xz, int yz):
|
|
|
|
return Pos(self.w, self.h, xz + 1, yz + 1)
|
|
|
|
|
|
|
|
cdef inline IAch(self, int xz, int yz):
|
|
|
|
return xz + (self.w * yz)
|
|
|
|
|
|
|
|
cdef PutAch(self, int ach, int x, int y):
|
|
|
|
if not (x < 1 or y < 1 or x > self.w or y > self.h): #clip
|
|
|
|
self.rgach[self.IAch(x - 1, y - 1)] = ach
|
|
|
|
#self.mpyzxz_ach[y-1][x-1] = ach
|
|
|
|
|
|
|
|
cdef inline GetAch(self, int x, int y):
|
|
|
|
return self.rgach[self.IAch(x - 1, y - 1)]
|
|
|
|
|
|
|
|
cdef PutRgach(self, rgach, int x, int y):
|
|
|
|
cdef int xz = x - 1
|
|
|
|
cdef int iach
|
|
|
|
if xz < self.w:
|
|
|
|
if xz < 0:
|
|
|
|
rgach = rgach[min(-xz, len(rgach)):]
|
|
|
|
xz = 0
|
|
|
|
if xz + len(rgach) >= self.w:
|
|
|
|
rgach = rgach[:self.w - xz]
|
|
|
|
iach = self.IAch(xz, y - 1)
|
|
|
|
for ach in rgach:
|
|
|
|
if ach != achBlankI:
|
|
|
|
self.rgach[iach] = ach
|
|
|
|
iach = iach + 1
|
|
|
|
#self.mpyzxz_ach[y-1][xz:xz + len(rgach)] = rgach
|
|
|
|
|
|
|
|
cdef PutSt(self, char *st, int x, int y, int colFg = WHITE, int colBg=BLACK):
|
|
|
|
if y < 1 or y > self.h:
|
|
|
|
return
|
|
|
|
cdef int cch = len(st)
|
|
|
|
cdef int ichStart = 0
|
|
|
|
cdef int xz = x - 1
|
|
|
|
if xz < 0:
|
|
|
|
ichStart = (-xz)
|
|
|
|
cch = cch - ichStart
|
|
|
|
xz = 0
|
|
|
|
cch = min(cch, self.w - xz)
|
|
|
|
cdef UAch uach
|
|
|
|
uach.sach.fgCol = colFg
|
|
|
|
uach.sach.bgCol = colBg
|
|
|
|
cdef int iach = self.IAch(xz, y - 1)
|
|
|
|
for ich in range(ichStart, ichStart + cch):
|
|
|
|
uach.sach.ch = st[ich]
|
|
|
|
self.rgach[iach] = uach.ach
|
|
|
|
iach = iach + 1
|
|
|
|
|
|
|
|
#self.PutRgach([MkAch(ch, colFg, colBg) for ch in st], x, y)
|
|
|
|
|
|
|
|
cdef Fill(self, int ach, int wIn, int hIn, int x = 1, int y = 1):
|
|
|
|
if x > self.w or y > self.h or ach == achBlankI:
|
|
|
|
return
|
|
|
|
cdef int xz = max(x - 1, 0)
|
|
|
|
cdef int yz = max(y - 1, 0)
|
|
|
|
cdef int w = min(self.w - xz, wIn)
|
|
|
|
cdef int h = min(self.h - yz, hIn)
|
|
|
|
cdef int iach
|
|
|
|
for yzT in range(yz, yz + h):
|
|
|
|
iach = self.IAch(xz, yzT)
|
|
|
|
for xzT in range(w):
|
|
|
|
self.rgach[iach] = ach
|
|
|
|
iach = iach + 1
|
|
|
|
#self.mpyzxz_ach[yzT][xz:xz + w] = ach
|
|
|
|
|
|
|
|
cdef PutAscr(self, AscrI ascr, int x=1, int y=1):
|
|
|
|
if x > self.w or y > self.h:
|
|
|
|
return
|
|
|
|
cdef int xz = max(x - 1, 0)
|
|
|
|
cdef int yz = max(y - 1, 0)
|
|
|
|
cdef int w = min(self.w - xz, ascr.w)
|
|
|
|
cdef int h = min(self.h - yz, ascr.h)
|
|
|
|
cdef int yzOther = 0
|
|
|
|
cdef int iach, iachOther, ach
|
|
|
|
for yzT in range(yz, yz + h):
|
|
|
|
iach = self.IAch(xz, yzT)
|
|
|
|
iachOther = ascr.IAch(0, yzOther)
|
|
|
|
for xzT in range(w):
|
|
|
|
ach = ascr.rgach[iachOther]
|
|
|
|
if ach != achBlankI:
|
|
|
|
self.rgach[iach] = ach
|
|
|
|
iach = iach + 1
|
|
|
|
iachOther = iachOther + 1
|
|
|
|
yzOther = yzOther + 1
|
2011-04-12 15:37:52 +00:00
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
cdef AstDiff(self, AscrI ascr):
|
|
|
|
assert self.w == ascr.w and self.h == ascr.h
|
|
|
|
cdef int xz = 0
|
|
|
|
cdef int yz = 0
|
|
|
|
cdef int xzPred = -1
|
|
|
|
cdef int achPrev = achInvdI
|
|
|
|
cdef int achBeforeEOL = achInvdI
|
|
|
|
cdef int achOld, achNew, achNewRaw
|
|
|
|
cdef int achSpace = MkAch(' ')
|
|
|
|
|
|
|
|
rgast = []
|
|
|
|
for iach in range(self.w * self.h):
|
|
|
|
achOld = self.rgach[iach]
|
|
|
|
achNewRaw = ascr.rgach[iach]
|
|
|
|
if achNewRaw == achBlankI:
|
|
|
|
achNew = achSpace
|
|
|
|
else:
|
|
|
|
achNew = achNewRaw
|
|
|
|
if xz == self.w - 2:
|
|
|
|
achBeforeEOL = achNew
|
|
|
|
if achOld != achNewRaw:
|
|
|
|
if xz == self.w - 1:
|
|
|
|
# Linewrap avoidance algorithm:
|
|
|
|
# when drawing the last character on a line, draw it in the space occupied by the character before.
|
|
|
|
rgast.append("%s%d;%dH" % (esc, yz + 1, xz))
|
|
|
|
rgast.append(AstFromAch(achNew, achInvdI))
|
|
|
|
# then, move the cursor back onto the character we just drew, and perform an insert.
|
|
|
|
rgast.append("%sD%s@" % (esc, esc))
|
|
|
|
# finally, draw the character before the last character in the line.
|
|
|
|
rgast.append(AstFromAch(achBeforeEOL, achNew))
|
2020-06-28 03:03:24 +00:00
|
|
|
achPrev = achBeforeEOL
|
2011-03-19 00:10:02 +00:00
|
|
|
else:
|
|
|
|
if xz != xzPred:
|
|
|
|
xzPred = xz
|
|
|
|
rgast.append("%s%d;%dH" % (esc, yz + 1, xz + 1))
|
|
|
|
achPrev = achInvdI
|
|
|
|
rgast.append(AstFromAch(achNew, achPrev))
|
2020-06-28 03:03:24 +00:00
|
|
|
achPrev = achNew
|
2011-03-19 00:10:02 +00:00
|
|
|
|
|
|
|
xzPred = xzPred + 1
|
|
|
|
xz = xz + 1
|
|
|
|
if xz == self.w:
|
|
|
|
xz = 0
|
|
|
|
xzPred = -1
|
|
|
|
yz = yz + 1
|
|
|
|
return "".join(rgast)
|
2011-04-12 15:37:52 +00:00
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
cdef Hst(self):
|
|
|
|
rgst = ["<pre style='font-family:\"Courier New\", Courier, System, monospace'>"]
|
|
|
|
cdef int achPrev = achInvdI
|
|
|
|
cdef int xz = 0
|
|
|
|
cdef int ach
|
|
|
|
for iach in range(self.w * self.h):
|
|
|
|
ach = self.rgach[iach]
|
|
|
|
rgst.append(HstFromAch(ach, achPrev))
|
|
|
|
achPrev = ach
|
|
|
|
xz = xz + 1
|
|
|
|
if xz == self.w:
|
|
|
|
xz = 0
|
|
|
|
rgst.append("<br>")
|
|
|
|
|
|
|
|
rgst.append("</span></pre>")
|
|
|
|
return ''.join(rgst)
|
2011-04-12 15:37:52 +00:00
|
|
|
|
2011-03-19 00:10:02 +00:00
|
|
|
def FKeyPrintable(key):
|
|
|
|
return type(key) == str and (ord(key) >= 32 and ord(key) <= 126)
|