ref: d180b70c6c69ffe8168cc8571772ad6e15ac6aba
dir: /pack.myr/
use std
use sys
use "types"
pkg draw =
const pack : (dpy : display#, fmt : byte[:], vsz : std.size, args : ... -> void)
const flush : (dpy : display# -> bool)
const flushbuf : (dpy : display# -> bool)
;;
const pack = {dpy, fmt, vsz, args
var ap
var sz, b, o
ap = std.vastart(&args)
sz = fixsize(fmt) + vsz
b = ensure(dpy, sz)
o = 0
for c : fmt
match (c : char)
| 'b':
b[o] = std.vanext(&ap)
o += 1
| 's':
var v : int16 = std.vanext(&ap)
std.putle16(b[o:o+2], v)
o += 2
| 'i':
var v : int32 = std.vanext(&ap)
std.putle32(b[o:o+4], v)
o += 4
| 'p':
var p : point = std.vanext(&ap)
std.putle32(b[o + 0:o + 4], p.x)
std.putle32(b[o + 4:o + 8], p.y)
o += 2*4
| 'r':
var r : rect = std.vanext(&ap)
std.putle32(b[o+ 0:o+ 4], r.x0)
std.putle32(b[o+ 4:o+ 8], r.y0)
std.putle32(b[o+ 8:o+12], r.x1)
std.putle32(b[o+12:o+16], r.y1)
o += 4*4
| 'S':
var s : byte[:] = std.vanext(&ap)
b[o++] = (s.len : byte)
std.slcp(b[o:o+s.len], s)
o += s.len
| 'I':
var s : int16[:] = std.vanext(&ap)
for var i = 0; i < s.len; i++
std.putle16(b[o:o+2], s[i])
o += 2
;;
| 'd':
var d : byte[:] = std.vanext(&ap)
std.slcp(b[o:o+d.len], d)
o += d.len
| ' ':
/* for readability of format strings */
| chr:
std.fatal("unknown specifier {} in pack\n", chr)
;;
;;
}
const fixsize = {fmt
var sz
sz = 0
for c : fmt
match (c : char)
| 'b': sz += 1
| 's': sz += 2
| 'i': sz += 4
| 'r': sz += 4*4
| 'p': sz += 2*4
| _: /* variable sizes */
;;
;;
-> sz
}
const ensure = {dpy, sz
var ret
if dpy.bufoff + sz > dpy.buf.len
flush(dpy)
;;
ret = dpy.buf[dpy.bufoff:dpy.bufoff + sz]
dpy.bufoff += sz
-> ret
}
const flush = {dpy
/* five bytes always reserved here */
dpy.buf[dpy.bufoff++] = ('v' : byte)
-> flushbuf(dpy)
}
const flushbuf = {dpy
var off, ret
var errbuf : byte[128]
off = 0
ret = true
while off != dpy.bufoff
match std.write(dpy.datafd, dpy.buf[off:dpy.bufoff])
| `std.Ok n: off += n
| `std.Err e:
sys.errstr(errbuf[:])
std.fatal("**error: {}\n", std.cstrconv(errbuf[:]))
ret = false
break
;;
;;
dpy.bufoff = 0
-> true
}