shithub: cursedfs

ref: 35bac6a836a15c60f6b7b6f26d0f8d8545e8e1a0
dir: /screen.c/

View raw version
#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();
			}
	}
}