ref: 8d6c1b01c6e17894cb1054d954d18272e71e5aae
dir: /draw.myr/
use std
use date
use iter
use termdraw
use "types"
use "irc"
pkg =
const redraw : (irc : irc# -> void)
;;
const redraw = {irc
var c, x, y, w, h, lh
if irc.term.width < 10 || irc.term.height < 5
-> void
;;
x = 0
y = 0
w = irc.term.width
h = irc.term.height
c = curchan(irc)
if irc.chandirty
lh = listheight(irc, 0, 1, w, h - 1)
drawbanner(irc, 0, 0, w, 1, c)
drawtext(irc, 0, 1, w, h - lh - 1, c)
drawlist(irc, 0, h - lh - 1, w, h - 1, c)
irc.chandirty = false
;;
if irc.cmddirty
drawinput(irc, 0, h - 1, w, h, c)
irc.cmddirty = false
;;
termdraw.flush(irc.term)
}
const drawbanner = {irc, x0, y0, x1, y1, c
var t
t = irc.term
termdraw.setbg(t, termdraw.Blue)
termdraw.clear(t, x0, y0, x1, y1)
termdraw.move(t, x0, y0)
termdraw.put(t, "{}", c.topic)
}
const drawtext = {irc, x0, y0, x1, y1, c
var height, margin, width, off
var t, dx, dy
var count
var x, y
t = irc.term
termdraw.setbg(t, termdraw.Default)
termdraw.clear(t, x0, y0, x1, y1)
termdraw.move(t, x0, y0)
dx = x1 - x0
dy = y1 - y0
count = 0
height = 0
width = dx
off = 0
/* nothing worth drawing... */
if dx <= c.gutter
-> void
;;
for (tm, ent) : iter.byreverse(c.hist[:c.hist.len - c.scroll])
margin = 0
match ent
| `Msg (m, ln):
margin = strwidth(x0, c.gutter, " | ") + c.gutter
width = strwidth(x0, margin, ln)
| `Act (m, ln):
margin = strwidth(x0, 0, " *")
width = strwidth(x0, margin, m)
width += strwidth(x0, margin, " ")
width += strwidth(x0, margin, ln)
| `Join user:
margin = strwidth(x0, 0, "#joined: ")
width = strwidth(x0, margin, user)
| `Part user:
margin = strwidth(x0, 0, "#parted: ")
width = strwidth(x0, margin, user)
| `Status msg:
margin = strwidth(x0, 0, "! ")
width = strwidth(x0, margin, msg)
;;
/* no point in drawing if all we draw is gutter */
if dx - margin <= 0
-> void
;;
height++
if width > 0
height += width / (dx - margin)
;;
count++
if height == dy
break
elif height > dy
off = (dx - margin)*(height - dy)
off = std.clamp(off, 0, width)
break
;;
;;
x = x0
y = y0
off = std.clamp(off, 0, width)
for (tm, h) : c.hist[c.hist.len - c.scroll - count:]
match h
| `Msg (m, ln):
termdraw.setattr(t, termdraw.Bold)
x = std.clamp(x0 + c.gutter - strwidth(x0, 0, m), 0, dx)
termdraw.move(t, x0 + c.gutter, y)
(x, y) = draw(t, m, x, y, x1, y1)
(x, y) = draw(t, " | ", x, y, x1, y1)
termdraw.setattr(t, lineattr(irc, ln[off:]))
(x, y) = draw(t, ln[off:], x, y, x1, y1)
termdraw.setattr(t, termdraw.Normal)
| `Act (m, ln):
termdraw.setattr(t, termdraw.Bold)
(x, y) = draw(t, " *", x0, y, x1, y1)
(x, y) = draw(t, m, x, y, x1, y1)
termdraw.setattr(t, lineattr(irc, ln[off:]))
(x, y) = draw(t, " ", x, y, x1, y1)
(x, y) = draw(t, ln[off:], x, y, x1, y1)
termdraw.setattr(t, termdraw.Normal)
| `Join user:
(x, y) = draw(t, "#joined ", x0, y, x1, y1)
(x, y) = draw(t, user[off:], x, y, x1, y1)
| `Part user:
(x, y) = draw(t, "#parted ", x0, y, x1, y1)
(x, y) = draw(t, user[off:], x, y, x1, y1)
| `Status msg:
(x, y) = draw(t, "! ", x0, y, x1, y1)
(x, y) = draw(t, msg[off:], x, y, x1, y1)
;;
y++
off = 0
if y >= y1
break
;;
;;
}
const strwidth = {x0, margin, str
var x
x = x0 + margin
for c : std.bychar(str)
match c
| '\t': x = (x / 8 + 1) * 8
| _: x += (std.cellwidth(c) : int)
;;
;;
-> x - (x0 + margin)
}
const draw = {t, msg, x0, y0, x1, y1
var x, y
x = x0
y = y0
for l : std.bychar(msg)
match l
| '\t':
x = (x / 8 + 1)*8
| '\n':
termdraw.put(t, "\\n")
x += 2
| chr:
if x < x1
termdraw.move(t, x, y)
termdraw.putc(t, chr)
x++
;;
;;
if x >= x1
x = x0
y++
;;
;;
-> (x, y)
}
const drawlist = {irc, x0, y0, x1, y1, c
var t, h
h = 1
t = irc.term
termdraw.setbg(t, termdraw.Blue)
termdraw.clear(t, x0, y0, x1, y1)
termdraw.move(t, x0, y0)
termdraw.putc(t, '|')
termdraw.put(t, "[{}]", irc.self.name)
for s : irc.srv
for ch : s.chan
if t.x + strwidth(t.x, 0, ch.name) + 4 >= x1
h++
termdraw.move(t, x0, y0 + h - 1)
;;
if ch.flagged
termdraw.setattr(t, termdraw.Bold)
termdraw.put(t, "[@{}]", ch.name)
termdraw.setattr(t, termdraw.Normal)
elif ch.stale
termdraw.put(t, "[*{}]", ch.name)
else
termdraw.put(t, "[ {}]", ch.name)
;;
;;
termdraw.setattr(t, termdraw.Normal)
termdraw.putc(t, '|')
;;
-> h
}
const drawinput = {irc, x0, y0, x1, y1, c
var t, chan, ln, cx, dx
dx = x1 - x0
t = irc.term
chan = std.fmt("[{}] ", c.name)
ln = inputstr(irc, chan, dx)
cx = x0 + (std.strcellwidth(chan) + irc.off : int)
if cx > dx
cx = dx
;;
termdraw.setbg(t, termdraw.Default)
termdraw.move(t, x0, y0)
termdraw.clear(t, x0, y0, x1, y1)
termdraw.put(t, "{}{}", chan, ln)
termdraw.cursorpos(t, cx, y0)
std.slfree(chan)
std.slfree(ln)
}
const listheight = {irc, x0, y0, x1, y1
var w, h
w = 0
h = 1
w += strwidth(x0, 0, "|")
w += strwidth(x0 + w, 0, "[ ]")
w += strwidth(x0 + w, 0, irc.self.name)
for s : irc.srv
for ch : s.chan
if x0 + w + strwidth(w, 0, ch.name) + 4 >= x1
h++
w = 0
;;
w += strwidth(x0 + w, 0, "[ ]")
w += strwidth(x0 + w, 0, ch.name)
;;
w += strwidth(x0 + w, 0, "|")
;;
-> h
}
const lineattr = {irc, ln
match cursrv(irc)
| `std.None: -> termdraw.Normal
| `std.Some srv:
match std.strfind(ln, srv.nick)
| `std.Some _: -> termdraw.Italic
| `std.None: -> termdraw.Normal
;;
;;
}
const inputstr = {irc, chan, dx
var w, s, o
var start, end
s = irc.cmd
o = (irc.off : int)
dx -= strwidth(0, 0, chan)
w = 0
start = 0
end = 0
for var i = 0; i < s.len; i++
w += std.cellwidth(s[i])
if w >= dx
break
;;
end++
;;
while end < s.len && irc.off >= (w : std.size)
start++
while std.cellwidth(s[end]) == 0
start++
;;
w += std.cellwidth(s[end])
end++
while end < s.len && std.cellwidth(s[end]) == 0
end++
;;
;;
-> getstr(s[start:end])
}