218 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| Copyright (C) 2015-2019 The University of Notre Dame
 | |
| This software is distributed under the GNU General Public License.
 | |
| See the file LICENSE for details.
 | |
| */
 | |
| 
 | |
| #include "console.h"
 | |
| #include "serial.h"
 | |
| #include "graphics.h"
 | |
| #include "kmalloc.h"
 | |
| #include "string.h"
 | |
| 
 | |
| struct console {
 | |
| 	struct window *window;
 | |
| 	struct graphics *gx;
 | |
| 	int xsize;
 | |
| 	int ysize;
 | |
| 	int xpos;
 | |
| 	int ypos;
 | |
| 	int onoff;
 | |
| 	int refcount;
 | |
| };
 | |
| 
 | |
| struct console console_root = {0};
 | |
| 
 | |
| static struct graphics_color bgcolor = { 0, 0, 0 };
 | |
| static struct graphics_color fgcolor = { 255, 255, 255 };
 | |
| 
 | |
| struct console * console_create_root()
 | |
| {
 | |
| 	console_root.window = window_create_root();
 | |
| 	console_root.gx = window_graphics(console_root.window);
 | |
| 	console_reset(&console_root);
 | |
| 	console_putstring(&console_root,"\nconsole: initialized\n");
 | |
| 	return &console_root;
 | |
| }
 | |
| 
 | |
| void console_reset( struct console *d )
 | |
| {
 | |
| 	if(!d || !d->gx) return;
 | |
| 	d->xpos = d->ypos = 0;
 | |
| 	d->xsize = graphics_width(d->gx) / 8;
 | |
| 	d->ysize = graphics_height(d->gx) / 8;
 | |
| 	d->onoff = 0;
 | |
| 	graphics_fgcolor(d->gx, fgcolor);
 | |
| 	graphics_bgcolor(d->gx, bgcolor);
 | |
| 	graphics_clear(d->gx, 0, 0, graphics_width(d->gx), graphics_height(d->gx));
 | |
| }
 | |
| 
 | |
| void console_heartbeat( struct console *d )
 | |
| {
 | |
| 	char c = d->onoff ? ' ' : '_';
 | |
| 	graphics_char(d->gx, d->xpos * 8, d->ypos * 8, c );
 | |
| 	d->onoff = !d->onoff;
 | |
| }
 | |
| 
 | |
| int console_post( struct console *c, const char *data, int size )
 | |
| {
 | |
| 	int total = 0;
 | |
| 
 | |
| 	struct event e;
 | |
| 	e.type = EVENT_KEY_DOWN;
 | |
| 	e.x = 0;
 | |
| 	e.y = 0;
 | |
| 
 | |
| 	while(size>0) {
 | |
| 		e.code = *data;
 | |
| 		window_post_events(c->window,&e,sizeof(e));
 | |
| 		size--;
 | |
| 		data++;
 | |
| 		total++;
 | |
| 	}
 | |
| 
 | |
| 	return total;
 | |
| }
 | |
| 
 | |
| int console_write( struct console *d, const char *data, int size )
 | |
| {
 | |
| 	graphics_char(d->gx, d->xpos * 8, d->ypos * 8, ' ');
 | |
| 
 | |
| 	int i;
 | |
| 	for(i = 0; i < size; i++) {
 | |
| 		char c = data[i];
 | |
| 		switch (c) {
 | |
| 		case 13:
 | |
| 		case 10:
 | |
| 			d->xpos = 0;
 | |
| 			d->ypos++;
 | |
| 			break;
 | |
| 		case '\f':
 | |
| 			d->xpos = d->ypos = 0;
 | |
| 			d->xsize = graphics_width(d->gx) / 8;
 | |
| 			d->ysize = graphics_height(d->gx) / 8;
 | |
| 			graphics_fgcolor(d->gx, fgcolor);
 | |
| 			graphics_bgcolor(d->gx, bgcolor);
 | |
| 			graphics_clear(d->gx, 0, 0, graphics_width(d->gx), graphics_height(d->gx));
 | |
| 			break;
 | |
| 		case '\b':
 | |
| 			d->xpos--;
 | |
| 			break;
 | |
| 		default:
 | |
| 			graphics_char(d->gx, d->xpos * 8, d->ypos * 8, c);
 | |
| 			d->xpos++;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		if(d->xpos < 0) {
 | |
| 			d->xpos = d->xsize - 1;
 | |
| 			d->ypos--;
 | |
| 		}
 | |
| 
 | |
| 		if(d->xpos >= d->xsize) {
 | |
| 			d->xpos = 0;
 | |
| 			d->ypos++;
 | |
| 		}
 | |
| 
 | |
| 		if(d->ypos >= d->ysize) {
 | |
| 			d->xpos = d->ypos = 0;
 | |
| 			d->xsize = graphics_width(d->gx) / 8;
 | |
| 			d->ysize = graphics_height(d->gx) / 8;
 | |
| 			graphics_fgcolor(d->gx, fgcolor);
 | |
| 			graphics_bgcolor(d->gx, bgcolor);
 | |
| 			graphics_clear(d->gx, 0, 0, graphics_width(d->gx), graphics_height(d->gx));
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 	graphics_char(d->gx, d->xpos * 8, d->ypos * 8, '_');
 | |
| 	return i;
 | |
| }
 | |
| 
 | |
| int console_read( struct console *c, char *data, int length )
 | |
| {
 | |
| 	int total=0;
 | |
| 
 | |
| 	struct event e;
 | |
| 	while(length>0 && window_read_events(c->window,&e,sizeof(e))) {
 | |
| 		if(e.type==EVENT_KEY_DOWN) {
 | |
| 			*data = e.code;
 | |
| 			length--;
 | |
| 			total++;
 | |
| 			data++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return total;
 | |
| }
 | |
| 
 | |
| int console_read_nonblock( struct console *c, char *data, int length )
 | |
| {
 | |
| 	int total=0;
 | |
| 
 | |
| 	struct event e;
 | |
| 	while(length>0 && window_read_events_nonblock(c->window,&e,sizeof(e))) {
 | |
| 		if(e.type==EVENT_KEY_DOWN) {
 | |
| 			*data = e.code;
 | |
| 			length--;
 | |
| 			total++;
 | |
| 			data++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return total;
 | |
| }
 | |
| 
 | |
| int console_getchar( struct console *c )
 | |
| {
 | |
| 	char ch;
 | |
| 	if(console_read(c,&ch,1)>0) {
 | |
| 		return ch;
 | |
| 	} else {
 | |
| 		return 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void console_putchar( struct console *c, char ch )
 | |
| {
 | |
| 	console_write(c,&ch,1);
 | |
| }
 | |
| 
 | |
| void console_putstring( struct console *c, const char *str)
 | |
| {
 | |
| 	console_write(c,str,strlen(str));
 | |
| }
 | |
| 
 | |
| struct console *console_create( struct window *w )
 | |
| {
 | |
| 	struct console *c = kmalloc(sizeof(*c));
 | |
| 	c->window = window_addref(w);
 | |
| 	c->gx = window_graphics(w);
 | |
| 	c->refcount = 1;
 | |
| 	console_reset(c);
 | |
| 	return c;
 | |
| }
 | |
| 
 | |
| struct console *console_addref( struct console *c )
 | |
| {
 | |
| 	c->refcount++;
 | |
| 	return c;
 | |
| }
 | |
| 
 | |
| void console_delete( struct console *c )
 | |
| {
 | |
| 	if(c==&console_root) return;
 | |
| 
 | |
| 	c->refcount--;
 | |
| 	if(c->refcount==0) {
 | |
| 		window_delete(c->window);
 | |
| 		kfree(c);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void console_size( struct console *c, int *xsize, int *ysize )
 | |
| {
 | |
| 	*xsize = c->xsize;
 | |
| 	*ysize = c->ysize;
 | |
| }
 | |
| 
 |