ref: 35bac6a836a15c60f6b7b6f26d0f8d8545e8e1a0
dir: /screen.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <event.h>
#include "fs.h"
Point p; // unused?
Font *ourfont; // VGA
Image *brush; // For drawing the text
Rune *s = L"☺☹σπß"; // for testing
int bwidth = 4; // border width of rio win
Rune ***sbuf, **ebuf; // screen buffer, empty buffer
usize sheight = 25, swidth = 80; // screen height, width
Lock slock; // screen buffer lock
/* Menus */
char *buttons[] = {"exit", 0};
Menu menu = { buttons };
// Free a 2D buffer
void
freebuf(Rune **buf, usize height)
{
int i;
for(i = 0; i < height; i++)
free(buf[i]);
free(buf);
}
// Render the active buffer on a timer
void
renderbuf(void)
{
int i;
Point p;
lock(&slock);
Point at = screen->r.min;
for(i = 0; i < sheight; i++){
p = runestringsize(ourfont, (*sbuf)[i]);
runestring(
screen, at, display->black, ZP,
ourfont, (*sbuf)[i]
);
at.y += p.y;
}
unlock(&slock);
flushimage(display, 1);
}
// Handle resize events
void
eresized(int new)
{
if(new && getwindow(display, Refnone) < 0)
sysfatal("can't reattach to window");
/* Store new screen coordinates for collision detection */
p = Pt(Dx(screen->r), Dy(screen->r));
/* Draw the background DWhite */
draw(screen, insetrect(screen->r, bwidth),
allocimage(display, Rect(0, 0, 1, 1),
screen->chan, 1, DWhite),
nil, ZP
);
}
// Initialize the screen buffer
void
initbuf(void)
{
int y, x;
ourfont = openfont(display, "/lib/font/bit/vga/unicode.font");
p = runestringsize(ourfont, s);
lock(&slock);
sbuf = calloc(sheight, sizeof (Rune**));
*sbuf = calloc(sheight, sizeof (Rune*));
ebuf = calloc(sheight, sizeof (Rune*));
for(y = 0; y < sheight; y++){
(*sbuf)[y] = calloc(swidth+1, sizeof (Rune));
ebuf[y] = calloc(swidth+1, sizeof (Rune));
for(x = 0; x < swidth; x++){
(*sbuf)[y][x] = L'☺';
ebuf[y][x] = L' ';
}
}
unlock(&slock);
}
// Initialize the screen, spins forever
void
initscreen(void*)
{
Event ev;
int e, timer;
/* Initiate graphics and mouse */
if(initdraw(nil, nil, "cursedfs") < 0)
sysfatal("initdraw failed: %r");
einit(Emouse);
// Timer in ms
timer = etimer(0, 15);
/* Simulate a resize event to draw the background
* and acquire the screen dimensions */
initbuf();
// Set the screen size (after initbuf)
//echo resize -dx 100 -dy 100 > /dev/wctl
int fd;
char *str;
fd = open("/dev/wctl", OWRITE);
usize width = (ourfont->width * swidth) + 2*bwidth +1;
usize height = (ourfont->height * sheight) + 2*bwidth +1;
str = smprint("resize -dx %ld -dy %ld\n", width, height);
int out = write(fd, str, strlen(str));
if(out < 1)
sysfatal("err: /dev/wctl write failed → %r");
close(fd);
free(str);
eresized(0);
/* Main event loop */
for(;;){
e = event(&ev);
/* If there is a mouse event, the rightmost button
* pressed and the first menu option selected
* then exit.. */
if(
(e == Emouse)
&& (ev.mouse.buttons & 4)
&& (emenuhit(3, &ev.mouse, &menu) == 0)
)
threadexitsall(nil);
else
if(e == timer){
// Might not want this
eresized(0);
renderbuf();
}
}
}