Mercurial > hg > forks > pwpunix
diff pwplib/linuxcon.c @ 0:acb5694e93d9
Initial import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 18 May 2010 04:25:44 +0300 |
parents | |
children | 2c72092554fa |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pwplib/linuxcon.c Tue May 18 04:25:44 2010 +0300 @@ -0,0 +1,393 @@ +#include "config.h" + +#ifdef DRIVE_LINUXCON + +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/kd.h> + +#include "pwplib.h" + +#include "tty.h" + +/******************** vcsa code ********************/ + +struct{ + int fd; + int width,height; + + int fontw,fonth; + u8*fontd; + char*fontd_tab; + + /* add cfd (control fd) or something */ +}pwp_linuxcon; + +void vcsa_dump_attr() +{ + char*buf=pwplib.videobuf.d; + int ptr=4+pwp_linuxcon.width* + ((pwp_linuxcon.height-pwplib.videobuf.height)&~1); + if(ptr<4)ptr=4; + + if(pwp_linuxcon.width==pwplib.videobuf.width) + { + lseek(pwp_linuxcon.fd,ptr,SEEK_SET); + write(pwp_linuxcon.fd,buf, + pwplib.videobuf.width*pwplib.videobuf.height*2); + }else + { + int y=0,y1=pwplib.videobuf.height,w=pwplib.videobuf.width; + ptr+=((pwp_linuxcon.width-pwplib.videobuf.width)&~1); + if(y1>pwp_linuxcon.height)y1=pwp_linuxcon.height; + if(w>pwp_linuxcon.width)w=pwp_linuxcon.width; + w<<=1; + for(;y<y1;y++) + { + lseek(pwp_linuxcon.fd,ptr,SEEK_SET); + write(pwp_linuxcon.fd,buf,w); + buf+=pwplib.videobuf.width*2; + ptr+=pwp_linuxcon.width*2; + } + } + + pwplib.timer_counter+=pwp_linuxcon.width*pwp_linuxcon.height*2; +} + +int vcsa_get() +{ + int vcsa; + int majmin; + + { struct stat sbuf; + int stderr2=dup(fileno(stderr)); + fstat(stderr2,&sbuf); + majmin=sbuf.st_rdev; + close(stderr2); + } + + if((majmin&~0x63)==4*256) + { + char buf[20]; + sprintf(buf,"/dev/vcsa%i",majmin&63); + vcsa=open(buf,O_RDWR); + if(vcsa>=0)return vcsa; + } + vcsa=open("/dev/vcsa",O_RDWR); + if(vcsa>=0)return vcsa; + + return -1; +} + +int vcsa_init() /* init vcsa device */ +{ + unsigned char vcsahdr[4]; + int vcsa=vcsa_get(); + if(vcsa<0)return 0; + + read(vcsa,vcsahdr,4); + pwp_linuxcon.fd=vcsa; + pwplib.videobuf.height=pwp_linuxcon.height=vcsahdr[0]; + pwplib.videobuf.width=pwp_linuxcon.width=vcsahdr[1]; + + pwpwrite("* using vcsa device\n"); + + pwplib.dump_attr=vcsa_dump_attr; + return 1; +} + + +/********************************************************/ + +/*** some people are lazy to update their headers ... ***/ + +#ifndef KDFONTOP +#define KDFONTOP 0x4B72 + +struct console_font_op { + unsigned int op; + unsigned int flags; + unsigned int width, height; + unsigned int charcount; + unsigned char *data; +}; + +#define KD_FONT_OP_SET 0 +#define KD_FONT_OP_GET 1 +#define KD_FONT_OP_SET_DEFAULT 2 +#define KD_FONT_OP_COPY 3 + +#define KD_FONT_FLAG_DONT_RECALC 1 +#endif + +/********************************************/ + +enum +{ + GLY_CRAP=0, + GLY_BLANK, + GLY_FULL, + GLY_TOP, + GLY_BOTTOM, + GLY_LEFT, + GLY_RIGHT, +}; + +int tty_linux_setfont(char*fontd,int w,int h) +{ + struct console_font_op fontop; + fontop.op=KD_FONT_OP_SET; + fontop.flags=0; + fontop.data=fontd; + fontop.charcount=256; + fontop.width=w; + fontop.height=h; + + return ioctl(2,KDFONTOP,&fontop); +} + +int tty_linux_setfont_tab() +{ + char*font=malloc(pwp_linuxcon.fontw*32*sizeof(char)); + char*f=font, + *s=pwp_linuxcon.fontd_tab; + + int i,x,y; + + for(i=0;i<256;i++) + for(y=0;y<32;y++) + { + int b=0,x1=(pwp_linuxcon.fontw+7)&~7; + for(x=0;x<x1;x++) + { + int pix; + + if(y<pwp_linuxcon.fonth && + x<pwp_linuxcon.fontw) + pix=*s++?1:0;else pix=0; + + b<<=1; + b|=pix; + + if((x&7)==7) + { + *f++=b; + b=0; + } + } + } + + return tty_linux_setfont(font,pwp_linuxcon.fontw,pwp_linuxcon.fonth); +} + +void tty_linux_restorefont() +{ + tty_linux_setfont( + pwp_linuxcon.fontd, + pwp_linuxcon.fontw, + pwp_linuxcon.fonth); +} + +int tty_linux_fixfont() +{ +#if 0 + char newfont[pwp_linuxcon.fontw* + pwp_linuxcon.fonth*sizeof(char)]; + + glyphgen_fixtoibm( + pwp_linuxcon.fontd_tab, + pwp_linuxcon.fontw, + pwp_linuxcon.fonth); + + return tty_linux_setfont_tab(); +#endif + + return 0; +} + +/**********************************/ + +int tty_linux_analyzefont() +{ + u8 analysis[256]; + + u8*s=pwp_linuxcon.fontd; + char*d=pwp_linuxcon.fontd_tab; + int c=0; + +/* fprintf(stderr,"font analysis?\n");*/ + + for(;c<256;c++) + { + int x0=33,x1=-1,y0=33,y1=-1,x,y; + int dens=0; + + for(y=0;y<32;y++) + { + int byte; + for(x=0;x<pwp_linuxcon.fontw;x++) + { + if(!(x&7))byte=*s++; + +/* if(y<pwp_linuxcon.fonth)*d++=byte&128;*/ + + if(byte&128) + { + if(x<x0)x0=x; + if(x>x1)x1=x+1; + if(y<y0)y0=y; + if(y>y1)y1=y+1; + dens++; + } + byte<<=1; + } + } + + {int a=GLY_CRAP; + int w=(x1-x0),h=(y1-y0); + + if(h<=0)a=GLY_BLANK; + else + { + if(w>=pwp_linuxcon.fontw-1) + { + if(h>=pwp_linuxcon.fontw-1)a=GLY_FULL; + else + if(y1>=pwp_linuxcon.fontw-2)a=GLY_BOTTOM; + else + if(!y0)a=GLY_TOP; + } + else + if(h>=pwp_linuxcon.fonth-1) + { + if(x1>=pwp_linuxcon.fonth-2)a=GLY_RIGHT; + else + if(!x0)a=GLY_LEFT; + } + } + analysis[c]=a; +/* if(a)fprintf(stderr,"char %d: %d\n",c,a);*/ + } + } + + if(analysis[176]==GLY_FULL && + analysis[177]==GLY_FULL && + analysis[178]==GLY_FULL && + analysis[219]==GLY_FULL && + analysis[220]==GLY_BOTTOM && + analysis[223]==GLY_TOP) return 2; + +/* fprintf(stderr,"done\n");*/ + + return 1; +} + +int tty_linux_getfont() +{ + { + struct console_font_op fontop; + fontop.op=KD_FONT_OP_GET; + fontop.flags=0; + fontop.data=NULL; + fontop.charcount=0; + + /* if handle 2 doesn't work, try handles 1 and 0? + also with vcsa */ + + /* use this bitreverter somewhere (X11-1bpp code?) not here. + replaces lookups in fast machines. + + a=((a&0xf0f0f0f0)>>4)|((a&0x0f0f0f0f)<<4); + a=((a&0xcccccccc)>>2)|((a&0x33333333)<<2); + a=((a&0xaaaaaaaa)>>1)|((a&0x55555555)<<1); + */ + + ioctl(2,KDFONTOP,&fontop); + if(fontop.charcount) + { + pwp_linuxcon.fontw=fontop.width; + pwp_linuxcon.fonth=fontop.height; + + if(!fontop.data) + { + fontop.data=malloc(((pwp_linuxcon.fontw+7)>>3)*32* + fontop.charcount*sizeof(u8)); + fontop.op=KD_FONT_OP_GET; + fontop.flags=KD_FONT_FLAG_DONT_RECALC; + if(ioctl(2,KDFONTOP,&fontop)<0) + goto oldcall; + } + + pwp_linuxcon.fontd=fontop.data; + goto gotfont; + } + } + + oldcall: + { + struct consolefontdesc fontx; + fontx.chardata=malloc(512*32*sizeof(u8)); + + if(ioctl(2,GIO_FONTX,&fontx)<0)return 0; + + pwp_linuxcon.fontw=8; + pwp_linuxcon.fonth=fontx.charheight; + pwp_linuxcon.fontd=fontx.chardata; + } + + gotfont: + + pwp_linuxcon.fontd_tab= + malloc(pwp_linuxcon.fontw*pwp_linuxcon.fonth*sizeof(char)); + + return tty_linux_analyzefont(); +} + +/********************************************************/ + +extern void tty_ansicol_dump_attr(); +extern void tty_ansicol_prep_attr(); + +int tty_linux_initstring() +{ + write(pwp_tty.fd,"\33[11m",5*sizeof(char)); /* select ibmpc charset */ + tty_vt_initstring(); +} + +int tty_linux_init() +{ + if(!vcsa_init()) + { + pwplib.dump_attr=tty_ansicol_dump_attr; + pwplib.prep_attr=tty_ansicol_prep_attr; + pwpwrite("* no vcsa access - using tty\n"); + /* send init */ + } + + {int i=tty_linux_getfont(); + + pwpwrite("* font analysis: "); + + if(i==0)pwpwrite("can't access - assuming ibm\n");else + if(i==1)pwpwrite("no ibm rasters - using ascii\n");else + if(i==2)pwpwrite("ibm rasters found - using ibm\n"); + + if(i==0 || i==2) conv_init(2,0,0); + else conv_init(2,2,1); + } + + tty_linux_initstring(); +} + +#endif + +/* + additional stuff: + + - font customization: + - save font + - if evil: if font bigger than 8x8, change to 8x8 + - include rasterchars (64 chars as in vt220 driver) + ... + - restore old font +*/