jehanne/sys/src/cmd/hmi/console/cga.c

141 lines
2.7 KiB
C

/*
* This file is part of Jehanne.
*
* Copyright (C) 2015 Giacomo Tesio <giacomo@tesio.it>
*
* Jehanne is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include "console.h"
enum {
Black = 0x00,
Blue = 0x01,
Green = 0x02,
Cyan = 0x03,
Red = 0x04,
Magenta = 0x05,
Brown = 0x06,
Grey = 0x07,
Bright = 0x08,
Blinking = 0x80,
kbAttr = (Black<<4)|Grey, /* (background<<4)|foreground */
Cursor = (Grey<<4)|Black,
};
enum {
Width = 80*2,
Height = 25,
};
static int cgapos;
static uint8_t CGA[16384];
static void
cgaputc(uint8_t c)
{
int i;
uint8_t *cga, *p;
cga = CGA;
cga[cgapos] = ' ';
cga[cgapos+1] = kbAttr;
switch(c){
case '\r':
break;
case '\n':
cgapos = cgapos/Width;
cgapos = (cgapos+1)*Width;
break;
case '\b':
if(cgapos >= 2)
cgapos -= 2;
break;
default:
cga[cgapos++] = c;
cga[cgapos++] = kbAttr;
break;
}
if(cgapos >= (Width*Height)){
memmove(cga, &cga[Width], Width*(Height-1));
p = &cga[Width*(Height-1)];
for(i = 0; i < Width/2; i++){
*p++ = ' ';
*p++ = kbAttr;
}
cgapos -= Width;
}
cga[cgapos] = ' ';
cga[cgapos+1] = Cursor;
}
static int32_t
cgaflush(int device)
{
int32_t w;
Dir *dirp;
w = 1; /* 0 must mean eof, thus this is the default */
if((dirp = dirfstat(device)) != nil){
if(dirp->length == 0)
w = pwrite(device, CGA, Width*Height, 0);
free(dirp);
} else {
w = pwrite(device, CGA, Width*Height, 0);
}
return w;
}
/* read from conswrites, write to device */
void
writecga(int conswrites, int device)
{
int32_t pid, r, w, i;
static uint8_t buf[ScreenBufferSize];
pid = getpid();
debug("writecga %d: started\n", pid);
do
{
r = read(conswrites, buf, ScreenBufferSize);
debug("writecga %d: read(conswrites) returns %d\n", pid, r);
for(i = 0; i < r; i++)
cgaputc(buf[i]);
w = cgaflush(device);
debug("writecga %d: cgaflush(device) returns %d\n", pid, w);
}
while(r > 0 && w > 0);
close(conswrites);
debug("writecga %d: close(%d)\n", pid, conswrites);
close(device);
debug("writecga %d: close(%d)\n", pid, device);
debug("writecga %d: shut down (r = %d, w = %d)\n", pid, r, w);
if(r < 0)
exits("writecga: read");
if(w < 0)
exits("writecga: write");
exits(nil);
}