# 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 . # # Copyright 2009, 2010, 2011, 2020 Jeremy Penner from tpers import TPrs import ansi_cython as ansi # probably reinventing the wheel :/ class Rgseq(TPrs): def InitPersistent(self, *rgseq): self.rgseq = rgseq def __len__(self): return sum([len(seq) for seq in self.rgseq]) def __getitem__(self, i): c = 0 for seq in self.rgseq: cSeq = len(seq) if i < c + cSeq: return seq[i - c] c = c + cSeq raise IndexError def index(self, o): c = 0 for seq in self.rgseq: try: iSeq = seq.index(o) return iSeq + c except ValueError: c = c + len(seq) raise ValueError class Snippet(object): def __init__(self, st, ichStart, ichLim): self.st = st self.ichStart = ichStart self.ichLim = ichLim def RgstWrapped(st, w, fForEditing = False, dxStart = 0): return [snippet.st for snippet in RgSnippetWrapped(st, w, fForEditing, dxStart)] def RgSnippetWrapped(st, w, fForEditing = False, xStart = 0): ichWrap = -1 ichStart = 0 for ich, ch in enumerate(st): if ch == '\n': assert not fForEditing, "no support yet for editing strings with newlines" ichWrap = ich if not fForEditing and ch == ' ': ichWrap = ich if (ich == ichStart + w - xStart) or (ch == '\n'): ichStartNew = ichWrap + 1 if ichWrap < 0: ichWrap = ich ichStartNew = ich elif fForEditing: # don't swallow spaces ichWrap = ichStartNew yield Snippet(st[ichStart:ichWrap], ichStart, ichStartNew) ichStart = ichStartNew ichWrap = -1 xStart = 0 if fForEditing and ch == ' ': ichWrap = ich if ichStart < len(st) or ichStart == 0: yield Snippet(st[ichStart:], ichStart, len(st)) # selection helpers def IoInc(rgo, io, fnSelectable, fRebound = True): io = io + 1 while io < len(rgo) and not fnSelectable(rgo[io]): io = io + 1 if io >= len(rgo) or not fnSelectable(rgo[io]): if fRebound: return IoDec(rgo, io, fnSelectable, False) return -1 return io def IoDec(rgo, io, fnSelectable, fRebound = True): io = io - 1 while io > 0 and not fnSelectable(rgo[io]): io = io - 1 if io < 0 or not fnSelectable(rgo[io]): if fRebound: return IoInc(rgo, io, fnSelectable, False) return -1 return io class Stedit(TPrs): def InitPersistent(self, dgEnter = None, stInitial = ""): self.dgEnter = dgEnter self.SetValue(stInitial) def SetValue(self, st): self.st = st self.ich = len(st) def GetValue(self): return self.st def StForSize(self, fSel = True): if fSel and self.ich == len(self.st): return self.st + "_" return self.st def HandleKey(self, key): if key == ansi.K_LEFT and self.ich > 0: self.ich = self.ich - 1 elif key == ansi.K_RIGHT and self.ich < len(self.st): self.ich = self.ich + 1 elif key == ansi.K_BACKSPACE and self.ich > 0: self.st = self.st[:self.ich - 1] + self.st[self.ich:] self.ich = self.ich - 1 elif key == ansi.K_DEL and self.ich < len(self.st): self.st = self.st[:self.ich] + self.st[self.ich + 1:] elif key == ansi.K_HOME: self.ich = 0 elif key == ansi.K_END: self.ich = len(self.st) elif ansi.FKeyPrintable(key): self.st = self.st[:self.ich] + key + self.st[self.ich:] self.ich = self.ich + 1 elif ansi.FEnter(key) and self.dgEnter != None: if not self.dgEnter(self.st): self.st = "" self.ich = 0 else: return False return True def DrawCursor(self, ascr, x, y, colFg, colBg, snippet): if self.ich >= snippet.ichStart and (snippet.ichLim < 0 or self.ich < snippet.ichLim): if self.ich == len(self.st): ch = ' ' else: ch = self.st[self.ich] ascr.PutAch(ansi.MkAch(ch, colFg, colBg), x + self.ich - snippet.ichStart, y)