diff --git a/src/conio/GNUmakefile b/src/conio/GNUmakefile index 859355f795150862347dcd4d3e8599219351852c..278e38a351939ef22b86aa7237ad6c3ebdff4c4c 100644 --- a/src/conio/GNUmakefile +++ b/src/conio/GNUmakefile @@ -8,14 +8,17 @@ OBJS += $(MTOBJODIR)$(DIRSEP)curs_cio$(OFILE) ifdef NO_X CFLAGS += -DNO_X else - OBJS += $(MTOBJODIR)$(DIRSEP)console$(OFILE) \ + OBJS += $(MTOBJODIR)$(DIRSEP)x_events$(OFILE) \ $(MTOBJODIR)$(DIRSEP)x_cio$(OFILE) + NEED_BITMAP := 1 endif ifdef WITH_SDL_AUDIO OBJS += $(MTOBJODIR)$(DIRSEP)sdl_con$(OFILE) + NEED_BITMAP := 1 else ifdef WITH_SDL + NEED_BITMAP := 1 OBJS += $(MTOBJODIR)$(DIRSEP)sdl_con$(OFILE) OBJS += $(MTOBJODIR)$(DIRSEP)sdlfuncs$(OFILE) ifeq ($(os),darwin) @@ -30,29 +33,17 @@ ifeq ($(os),netbsd) endif endif -$(MTOBJODIR)$(DIRSEP)console$(OFILE).static: - $(QUIET)$(DELETE) $(MTOBJODIR)$(DIRSEP)console$(OFILE)* - $(QUIET)touch $(MTOBJODIR)$(DIRSEP)console$(OFILE).static - -$(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic: - $(QUIET)$(DELETE) $(MTOBJODIR)$(DIRSEP)console$(OFILE)* - $(QUIET)touch $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic +ifdef NEED_BITMAP + OBJS += $(MTOBJODIR)$(DIRSEP)bitmap_con$(OFILE) +endif # CIOLIB Library Link Rule -ifdef STATIC -$(CIOLIB-MT_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).static $(MTOBJODIR) $(OBJS) -else -$(CIOLIB-MT_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic $(MTOBJODIR) $(OBJS) -endif +$(CIOLIB-MT_BUILD): $(MTOBJODIR) $(OBJS) @echo Creating $@ ... $(QUIET)$(AR) rc $@ $(OBJS) $(QUIET)$(RANLIB) $@ -ifdef STATIC -$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).static $(MTOBJODIR) $(OBJS) -else -$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic $(MTOBJODIR) $(OBJS) -endif +$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR) $(OBJS) @echo Creating $@ $(QUIET)$(MKSHLIB) $(LDFLAGS) $(OBJS) $(SHLIBOPTS) -o $@ diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c new file mode 100644 index 0000000000000000000000000000000000000000..0ad1682b0273d85c9a24fa5504ba39e7b861188f --- /dev/null +++ b/src/conio/bitmap_con.c @@ -0,0 +1,717 @@ +/* $Id$ */ + +#include <stdarg.h> +#include <stdio.h> /* NULL */ +#include <stdlib.h> +#include <string.h> + +#include "threadwrap.h" +#include "semwrap.h" +#include "gen_defs.h" +#include "genwrap.h" +#include "dirwrap.h" +#include "xpbeep.h" + +#if (defined CIOLIB_IMPORTS) + #undef CIOLIB_IMPORTS +#endif +#if (defined CIOLIB_EXPORTS) + #undef CIOLIB_EXPORTS +#endif + +#include "ciolib.h" +#include "keys.h" +#include "vidmodes.h" +#include "allfonts.h" + +static char *screen; +int screenwidth; +int screenheight; +#define PIXEL_OFFSET(x,y) ( (y)*screenwidth+(x) ) + +static int current_font=-99; +struct video_stats vstat; + +struct bitmap_callbacks { + void (*drawrect) (int xpos, int ypos, int width, int height, unsigned char *data); +}; + +pthread_mutex_t vstatlock; +pthread_mutex_t screenlock; +static struct bitmap_callbacks callbacks; +static unsigned char *font; + +struct rectangle { + int x; + int y; + int width; + int height; +}; + +static int update_rect(int sx, int sy, int width, int height, int force); + +/* Blinker Thread */ +static void blinker_thread(void *data) +{ + while(1) { + SLEEP(500); + pthread_mutex_lock(&vstatlock); + if(vstat.blink) + vstat.blink=FALSE; + else + vstat.blink=TRUE; + update_rect(0,0,0,0,FALSE); + pthread_mutex_unlock(&vstatlock); + } +} + +int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)) +{ + pthread_mutex_init(&vstatlock, NULL); + pthread_mutex_init(&screenlock, NULL); + pthread_mutex_lock(&vstatlock); + vstat.vmem=NULL; + pthread_mutex_unlock(&vstatlock); + + callbacks.drawrect=drawrect_cb; + _beginthread(blinker_thread,0,NULL); + + return(0); +} + +void send_rectangle(int xoffset, int yoffset, int width, int height, int force) +{ + unsigned char *rect; + int pixel=0; + int inpixel; + int x,y; + + pthread_mutex_lock(&screenlock); + if(callbacks.drawrect) { + if(xoffset < 0 || xoffset >= screenwidth || yoffset < 0 || yoffset >= screenheight || width <= 0 || width > screenwidth || height <=0 || height >screenheight) { + pthread_mutex_unlock(&screenlock); + return; + } + + rect=(unsigned char *)malloc(width*height*sizeof(unsigned char)); + if(!rect) { + pthread_mutex_unlock(&screenlock); + return; + } + + for(y=0; y<height; y++) { + inpixel=PIXEL_OFFSET(xoffset, yoffset+y); + for(x=0; x<width; x++) { + rect[pixel++]=vstat.palette[screen[inpixel++]]; + } + } + callbacks.drawrect(xoffset,yoffset,width,height,rect); + } + pthread_mutex_unlock(&screenlock); +} + +int bitmap_init_mode(int mode, int *width, int *height) +{ + int i; + char *newscreen; + + pthread_mutex_lock(&vstatlock); + + if(load_vmode(&vstat, mode)) { + pthread_mutex_unlock(&vstatlock); + return(-1); + } + + /* Initialize video memory with black background, white foreground */ + for (i = 0; i < vstat.cols*vstat.rows; ++i) + vstat.vmem[i] = 0x0700; + + pthread_mutex_lock(&screenlock); + screenwidth=vstat.charwidth*vstat.cols; + if(width) + *width=screenwidth; + screenheight=vstat.charheight*vstat.rows; + if(height) + *height=screenheight; + newscreen=realloc(screen, screenwidth*screenheight); + if(!newscreen) { + pthread_mutex_unlock(&screenlock); + pthread_mutex_unlock(&vstatlock); + return(-1); + } + screen=newscreen; + memset(screen,vstat.palette[0],screenwidth*screenheight); + pthread_mutex_unlock(&screenlock); + /* TODO: Re-enable this + send_rectangle(0,0,screenwidth,screenheight,TRUE); + */ + bitmap_loadfont(NULL); + /* TODO: Remove this next line */ + update_rect(1,1,cio_textinfo.screenwidth,cio_textinfo.screenheight,TRUE); + pthread_mutex_unlock(&vstatlock); + + cio_textinfo.attribute=7; + cio_textinfo.normattr=7; + cio_textinfo.currmode=mode; + cio_textinfo.screenheight=vstat.rows; + cio_textinfo.screenwidth=vstat.cols; + cio_textinfo.curx=1; + cio_textinfo.cury=1; + cio_textinfo.winleft=1; + cio_textinfo.wintop=1; + cio_textinfo.winright=cio_textinfo.screenwidth; + cio_textinfo.winbottom=cio_textinfo.screenheight; + + return(0); +} + +/********************************************************/ +/* High Level Stuff */ +/********************************************************/ + +/* Called from main thread only (Passes Event) */ +int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) +{ + int x,y; + unsigned char *out; + WORD sch; + + pthread_mutex_lock(&vstatlock); + if( sx < 1 + || sy < 1 + || ex < 1 + || ey < 1 + || sx > cio_textinfo.screenwidth + || sy > cio_textinfo.screenheight + || sx > ex + || sy > ey + || ex > cio_textinfo.screenwidth + || ey > cio_textinfo.screenheight + || fill==NULL) { + pthread_mutex_unlock(&vstatlock); + return(0); + } + + out=fill; + for(y=sy-1;y<ey;y++) { + for(x=sx-1;x<ex;x++) { + sch=*(out++); + sch |= (*(out++))<<8; + vstat.vmem[y*cio_textinfo.screenwidth+x]=sch; + } + } + update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE); + pthread_mutex_unlock(&vstatlock); + return(1); +} + +/* Called from main thread only */ +int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) +{ + int x,y; + unsigned char *out; + WORD sch; + + pthread_mutex_lock(&vstatlock); + + if( sx < 1 + || sy < 1 + || ex < 1 + || ey < 1 + || sx > cio_textinfo.screenwidth + || sy > cio_textinfo.screenheight + || sx > ex + || sy > ey + || ex > cio_textinfo.screenwidth + || ey > cio_textinfo.screenheight + || fill==NULL) { + pthread_mutex_unlock(&vstatlock); + return(0); + } + + out=fill; + for(y=sy-1;y<ey;y++) { + for(x=sx-1;x<ex;x++) { + sch=vstat.vmem[y*cio_textinfo.screenwidth+x]; + *(out++)=sch & 0xff; + *(out++)=sch >> 8; + } + } + pthread_mutex_unlock(&vstatlock); + return(1); +} + +/* Called from main thread only */ +void bitmap_setcursortype(int type) +{ + pthread_mutex_lock(&vstatlock); + switch(type) { + case _NOCURSOR: + vstat.curs_start=0xff; + vstat.curs_end=0; + break; + case _SOLIDCURSOR: + vstat.curs_start=0; + vstat.curs_end=vstat.charheight-1; + break; + default: + vstat.curs_start = vstat.default_curs_start; + vstat.curs_end = vstat.default_curs_end; + break; + } + update_rect(cio_textinfo.curx+cio_textinfo.winleft-1,cio_textinfo.cury+cio_textinfo.wintop-1,1,1,TRUE); + pthread_mutex_unlock(&vstatlock); +} + +int bitmap_setfont(int font, int force) +{ + int changemode=0; + int newmode=-1; + struct text_info ti; + char *old; + int ow,oh; + int row,col; + char *new; + int attr; + char *pold; + char *pnew; + + if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) + return(-1); + + if(conio_fontdata[font].eight_by_sixteen!=NULL) + newmode=C80; + else if(conio_fontdata[font].eight_by_fourteen!=NULL) + newmode=C80X28; + else if(conio_fontdata[font].eight_by_eight!=NULL) + newmode=C80X50; + + switch(vstat.charheight) { + case 8: + if(conio_fontdata[font].eight_by_eight==NULL) { + if(force) + return(-1); + else + changemode=1; + } + break; + case 14: + if(conio_fontdata[font].eight_by_fourteen==NULL) { + if(force) + return(-1); + else + changemode=1; + } + break; + case 16: + if(conio_fontdata[font].eight_by_sixteen==NULL) { + if(force) + return(-1); + else + changemode=1; + } + break; + } + if(changemode && newmode==-1) + return(-1); + current_font=font; + if(changemode) { + gettextinfo(&ti); + + attr=ti.attribute; + ow=ti.screenwidth; + oh=ti.screenheight; + + old=malloc(ow*oh*2); + if(old) { + gettext(1,1,ow,oh,old); + textmode(newmode); + new=malloc(ti.screenwidth*ti.screenheight*2); + pold=old; + pnew=new; + for(row=0; row<ti.screenheight; row++) { + for(col=0; col<ti.screenwidth; col++) { + if(row < oh) { + if(col < ow) { + *(new++)=*(old++); + *(new++)=*(old++); + } + else { + *(new++)=' '; + *(new++)=attr; + } + } + else { + *(new++)=' '; + *(new++)=attr; + } + } + if(row < oh) { + for(;col<ow;col++) { + old++; + old++; + } + } + } + puttext(1,1,ti.screenwidth,ti.screenheight,new); + free(pnew); + free(pold); + } + } + return(0); +} + +int bitmap_getfont(void) +{ + return(current_font); +} + +/* Called from event thread only */ +int bitmap_loadfont(char *filename) +{ + static char current_filename[MAX_PATH]; + unsigned int fontsize; + int fw; + int fh; + int ch; + int x; + int y; + int charrow; + int charcol; + FILE *fontfile; + + if(current_font==-99 || current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) { + for(x=0; conio_fontdata[x].desc != NULL; x++) { + if(!strcmp(conio_fontdata[x].desc, "Codepage 437 English")) { + current_font=x; + break; + } + } + if(conio_fontdata[x].desc==NULL) + current_font=0; + } + if(current_font==-1) + filename=current_filename; + else if(conio_fontdata[current_font].desc==NULL) + return(-1); + + pthread_mutex_lock(&vstatlock); + fh=vstat.charheight; + fw=vstat.charwidth/8+(vstat.charwidth%8?1:0); + + fontsize=fw*fh*256*sizeof(unsigned char); + + if(font) + free(font); + if((font=(unsigned char *)malloc(fontsize))==NULL) { + pthread_mutex_unlock(&vstatlock); + return(-1); + } + + if(filename != NULL) { + if(flength(filename)!=fontsize) { + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + if((fontfile=fopen(filename,"rb"))==NULL) { + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + if(fread(font, 1, fontsize, fontfile)!=fontsize) { + pthread_mutex_unlock(&vstatlock); + free(font); + fclose(fontfile); + return(-1); + } + fclose(fontfile); + current_font=-1; + if(filename != current_filename) + SAFECOPY(current_filename,filename); + } + else { + switch(vstat.charwidth) { + case 8: + switch(vstat.charheight) { + case 8: + if(conio_fontdata[current_font].eight_by_eight==NULL) { + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + memcpy(font, conio_fontdata[current_font].eight_by_eight, fontsize); + break; + case 14: + if(conio_fontdata[current_font].eight_by_fourteen==NULL) { + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + memcpy(font, conio_fontdata[current_font].eight_by_fourteen, fontsize); + break; + case 16: + if(conio_fontdata[current_font].eight_by_sixteen==NULL) { + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + memcpy(font, conio_fontdata[current_font].eight_by_sixteen, fontsize); + break; + default: + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + break; + default: + pthread_mutex_unlock(&vstatlock); + free(font); + return(-1); + } + } + + pthread_mutex_unlock(&vstatlock); + return(0); +} + +/* Called from events thread only */ +static void bitmap_draw_cursor(void) +{ + int x; + int y; + int attr; + int pixel; + int xoffset,yoffset; + int start,end; + int width; + + if(vstat.blink && !hold_update) { + pthread_mutex_lock(&vstatlock); + if(vstat.curs_start<=vstat.curs_end) { + xoffset=(cio_textinfo.curx+cio_textinfo.winleft-2)*vstat.charwidth; + yoffset=(cio_textinfo.cury+cio_textinfo.wintop-2)*vstat.charheight; + attr=cio_textinfo.attribute&0x0f; + start=vstat.curs_start; + end=vstat.curs_end; + width=vstat.charwidth; + pthread_mutex_unlock(&vstatlock); + + pthread_mutex_lock(&screenlock); + for(y=start; y<=end; y++) { + pixel=PIXEL_OFFSET(xoffset, yoffset+y); + for(x=0; x<width; x++) + screen[pixel++]=attr; + } + pthread_mutex_unlock(&screenlock); + send_rectangle(xoffset, yoffset+vstat.curs_start, vstat.charwidth, vstat.curs_end-vstat.curs_start+1,FALSE); + } + else + pthread_mutex_unlock(&vstatlock); + } +} + +/* Called from main thread only */ +void bitmap_gotoxy(int x, int y) +{ + static int lx=-1,ly=-1; + + pthread_mutex_lock(&vstatlock); + if((x != cio_textinfo.curx) || (y != cio_textinfo.cury)) { + vstat.curs_col=x+cio_textinfo.winleft-1; + vstat.curs_row=y+cio_textinfo.wintop-1; + cio_textinfo.curx=x; + cio_textinfo.cury=y; + } + if(!hold_update) { + /* Erase old cursor */ + if(lx != vstat.curs_col || ly != vstat.curs_row) + update_rect(lx,ly,1,1,TRUE); + /* Draw new cursor */ + bitmap_draw_cursor(); + lx=vstat.curs_col; + ly=vstat.curs_row; + } + pthread_mutex_unlock(&vstatlock); +} + +static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) +{ + int fg; + int bg; + int xoffset=(xpos-1)*vstat.charwidth; + int yoffset=(ypos-1)*vstat.charheight; + int x; + int y; + int fontoffset; + WORD sch; + + if(!screen) + return; + + if(!vstat.vmem) + return; + + sch=vstat.vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)]; + bg=(sch&0x7000)>>12; + fg=(sch&0x0f00)>>8; + fontoffset=(sch&0xff)*vstat.charheight; + + pthread_mutex_lock(&screenlock); + for(y=0; y<vstat.charheight; y++) { + for(x=0; x<vstat.charwidth; x++) { + if(font[fontoffset] & (0x80 >> x)) + screen[PIXEL_OFFSET(xoffset+x, yoffset+y)]=fg; + else + screen[PIXEL_OFFSET(xoffset+x, yoffset+y)]=bg; + } + fontoffset++; + } + pthread_mutex_unlock(&screenlock); + + return(0); +} + +static int update_rect(int sx, int sy, int width, int height, int force) +{ + int x,y; + unsigned int pos; + int redraw_cursor=0; + int lastcharupdated=0; + int fullredraw=0; + static unsigned short *last_vmem=NULL; + static struct video_stats vs; + struct rectangle this_rect; + int this_rect_used=0; + struct rectangle last_rect; + int last_rect_used=0; + + if(sx==0 && sy==0 && width==0 && height==0) + fullredraw=1; + + if(sx<=0) + sx=1; + if(sy<=0) + sy=1; + if(width<=0 || width>cio_textinfo.screenwidth) + width=cio_textinfo.screenwidth; + if(height<=0 || height>cio_textinfo.screenheight) + height=cio_textinfo.screenheight; + + if(vs.cols!=vstat.cols || vs.rows != vstat.rows || last_vmem==NULL) { + unsigned short *p; + + p=(unsigned short *)realloc(last_vmem, vstat.cols*vstat.rows*sizeof(unsigned short)); + if(p==NULL) + return(-1); + last_vmem=p; + memset(last_vmem, 255, vstat.cols*vstat.rows*sizeof(unsigned short)); + sx=1; + sy=1; + width=vstat.cols; + height=vstat.rows; + force=1; + vs.cols=vstat.cols; + vs.rows=vstat.rows; + } + + /* Redraw all chars */ + if(vstat.blink != vs.blink + || vstat.curs_col!=vs.curs_col + || vstat.curs_row!=vs.curs_row) + redraw_cursor=1; + + for(y=0;y<height;y++) { + for(x=0;x<width;x++) { + pos=(sy+y-1)*vstat.cols+(sx+x-1); + if(force + || (last_vmem[pos] != vstat.vmem[pos]) /* Different char */ + || (vstat.blink != vs.blink && vstat.vmem[pos]>>15) /* Blinking char */ + || (redraw_cursor && ((vs.curs_col==sx+x && vs.curs_row==sy+y) || (vstat.curs_col==sx+x && vstat.curs_row==sy+y))) /* Cursor */ + ) { + last_vmem[pos] = vstat.vmem[pos]; + bitmap_draw_one_char(sx+x,sy+y); + + if(lastcharupdated) { + this_rect.width+=vstat.charwidth; + lastcharupdated++; + } + else { + if(this_rect_used) { + send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE); + } + + this_rect.x=(sx+x-1)*vstat.charwidth; + this_rect.y=(sy+y-1)*vstat.charheight; + this_rect.width=vstat.charwidth; + this_rect.height=vstat.charheight; + this_rect_used=1; + lastcharupdated++; + } + if(!redraw_cursor && sx+x==vstat.curs_col && sy+y==vstat.curs_row) + redraw_cursor=1; + } + else { + if(this_rect_used) { + send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE); + this_rect_used=0; + } + if(last_rect_used) { + send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE); + last_rect_used=0; + } + + lastcharupdated=0; + } + pos++; + } + /* If ALL chars in the line were used, add to last_rect */ + if(lastcharupdated==width) { + if(last_rect_used) { + last_rect.height += vstat.charheight; + this_rect_used=0; + } + else { + last_rect=this_rect; + last_rect_used=1; + this_rect_used=0; + } + } + /* Otherwise send any stale line buffers */ + else + { + if(last_rect_used) { + send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE); + last_rect_used=0; + } + if(this_rect_used) { + send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height, FALSE); + this_rect_used=0; + } + } + lastcharupdated=0; + } + + if(this_rect_used) { + send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height, FALSE); + } + if(last_rect_used) { + send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE); + } + + /* Did we redraw the cursor? If so, update position */ + if(redraw_cursor) { + vs.curs_col=vstat.curs_col; + vs.curs_row=vstat.curs_row; + } + + /* On full redraws, save the last blink value */ + if(fullredraw) { + vs.blink=vstat.blink; + } + + if(redraw_cursor) + bitmap_draw_cursor(); + + return(0); +} diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h new file mode 100644 index 0000000000000000000000000000000000000000..58859654c30d2ecb7d5df6f1152d1eaa3ee5b4be --- /dev/null +++ b/src/conio/bitmap_con.h @@ -0,0 +1,23 @@ +#ifndef BITMAP_CON_H +#define BITMAP_CON_H + +#include "vidmodes.h" +#include "threadwrap.h" + +extern struct video_stats vstat; +extern pthread_mutex_t vstatlock; +extern sem_t drawn_sem; + +int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill); +int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill); +void bitmap_gotoxy(int x, int y); +void bitmap_setcursortype(int type); +int bitmap_setfont(int font, int force); +int bitmap_getfont(void); +int bitmap_loadfont(char *filename); + +void send_rectangle(int xoffset, int yoffset, int width, int height, int force); +int bitmap_init_mode(int mode, int *width, int *height); +int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)); + +#endif diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c index 3c38ff3ace22b0aa131bba4dfc823107f4610503..a8d6f251eaacd00a67c6dda8aa38ddfcbe463ec0 100644 --- a/src/conio/ciolib.c +++ b/src/conio/ciolib.c @@ -63,6 +63,7 @@ #undef getch #endif +#include "bitmap_con.h" #include "ansi_cio.h" CIOLIBEXPORT cioapi_t cio_api; @@ -120,11 +121,15 @@ int try_sdl_init(int mode) { if(!sdl_initciolib(mode)) { cio_api.mouse=1; - cio_api.puttext=sdl_puttext; - cio_api.gettext=sdl_gettext; + cio_api.puttext=bitmap_puttext; + cio_api.gettext=bitmap_gettext; + cio_api.gotoxy=bitmap_gotoxy; + cio_api.setcursortype=bitmap_setcursortype; + cio_api.setfont=bitmap_setfont; + cio_api.getfont=bitmap_getfont; + cio_api.loadfont=bitmap_loadfont; + cio_api.kbhit=sdl_kbhit; - cio_api.gotoxy=sdl_gotoxy; - cio_api.setcursortype=sdl_setcursortype; cio_api.getch=sdl_getch; cio_api.textmode=sdl_textmode; cio_api.showmouse=sdl_showmouse; @@ -139,9 +144,6 @@ int try_sdl_init(int mode) cio_api.copytext=sdl_copytext; cio_api.getcliptext=sdl_getcliptext; #endif - cio_api.setfont=sdl_setfont; - cio_api.getfont=sdl_getfont; - cio_api.loadfont=sdl_loadfont; cio_api.get_window_info=sdl_get_window_info; return(1); } @@ -153,16 +155,16 @@ int try_sdl_init(int mode) #ifndef NO_X int try_x_init(int mode) { - if(!console_init()) { + if(!x_init()) { cio_api.mode=CIOLIB_MODE_X; cio_api.mouse=1; - cio_api.puttext=x_puttext; - cio_api.gettext=x_gettext; - cio_api.gotoxy=x_gotoxy; - cio_api.setcursortype=x_setcursortype; - cio_api.setfont=x_setfont; - cio_api.getfont=x_getfont; - cio_api.loadfont=x_loadfont; + cio_api.puttext=bitmap_puttext; + cio_api.gettext=bitmap_gettext; + cio_api.gotoxy=bitmap_gotoxy; + cio_api.setcursortype=bitmap_setcursortype; + cio_api.setfont=bitmap_setfont; + cio_api.getfont=bitmap_getfont; + cio_api.loadfont=bitmap_loadfont; cio_api.beep=x_beep; cio_api.kbhit=x_kbhit; @@ -594,8 +596,8 @@ CIOLIBEXPORT void CIOLIBCALL ciolib_gettextinfo(struct text_info *info) BW40, BW80, C40, C80, or C4350 */ info->screenheight=cio_textinfo.screenheight; /* text screen's height */ info->screenwidth=cio_textinfo.screenwidth; /* text screen's width */ - info->curx=cio_textinfo.curx-cio_textinfo.winleft+1; /* x-coordinate in current window */ - info->cury=cio_textinfo.cury-cio_textinfo.wintop+1; /* y-coordinate in current window */ + info->curx=cio_textinfo.curx; /* x-coordinate in current window */ + info->cury=cio_textinfo.cury; /* y-coordinate in current window */ } } @@ -774,7 +776,7 @@ CIOLIBEXPORT void CIOLIBCALL ciolib_clrscr(void) cio_api.clrscr(); return; } - + width=cio_textinfo.winright-cio_textinfo.winleft+1; height=cio_textinfo.winbottom-cio_textinfo.wintop+1; buf=(unsigned char *)alloca(width*height*2); diff --git a/src/conio/console.c b/src/conio/console.c deleted file mode 100644 index bf40528f970d6fda278c3d976835978a6b204ca2..0000000000000000000000000000000000000000 --- a/src/conio/console.c +++ /dev/null @@ -1,1939 +0,0 @@ -/* - * Copyright (c) 1992, 1993, 1996 - * Berkeley Software Design, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Berkeley Software - * Design, Inc. - * - * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * July 22, 1999 - * - * To All Licensees, Distributors of Any Version of BSD: - * - * As you know, certain of the Berkeley Software Distribution ("BSD") source - * code files require that further distributions of products containing all or - * portions of the software, acknowledge within their advertising materials - * that such products contain software developed by UC Berkeley and its - * contributors. - * - * Specifically, the provision reads: - * - * " * 3. All advertising materials mentioning features or use of this software - * * must display the following acknowledgement: - * * This product includes software developed by the University of - * * California, Berkeley and its contributors." - * - * Effective immediately, licensees and distributors are no longer required to - * include the acknowledgement within advertising materials. Accordingly, the - * foregoing paragraph of those BSD Unix files containing it is hereby deleted - * in its entirety. - * - * William Hoskins - * Director, Office of Technology Licensing - * University of California, Berkeley - * - * - */ - -/* $Id$ */ - -/**************************************************************************** - * @format.tab-size 4 (Plain Text/Source Code File Header) * - * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * - * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * See the GNU Lesser General Public License for more details: lgpl.txt or * - * http://www.fsf.org/copyleft/lesser.html * - * * - * Anonymous FTP access to the most recent released source is available at * - * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * - * * - * Anonymous CVS access to the development source and modification history * - * is available at cvs.synchro.net:/cvsroot/sbbs, example: * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * - * (just hit return, no password is necessary) * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * - * * - * For Synchronet coding style and modification guidelines, see * - * http://www.synchro.net/source.html * - * * - * You are encouraged to submit any modifications (preferably in Unix diff * - * format) via e-mail to mods@synchro.net * - * * - * Note: If this box doesn't appear square, then you need to fix your tabs. * - ****************************************************************************/ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/types.h> - -#ifndef STATIC_LINK -#include <dlfcn.h> -#endif -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> /* malloc */ -#include <unistd.h> /* sysconf() */ - -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> - -#define CONSOLE_CLIPBOARD XA_PRIMARY - -#include <threadwrap.h> -#include <genwrap.h> -#include <dirwrap.h> - -#include "console.h" -#include "vidmodes.h" -#include "allfonts.h" - -#include "keys.h" -#include "mouse.h" - -#define CONSOLE_MAX_ROWS 61 -#define CONSOLE_MAX_COLS 81 - -/* Console definition variables */ -int console_new_mode=NO_NEW_MODE; -int CurrMode; -sem_t console_mode_changed; -sem_t copybuf_set; -sem_t pastebuf_set; -sem_t pastebuf_request; -sem_t font_set; -sem_t x11_loadfont; -sem_t x11_fontloaded; -int x_load_font_ret; -char font_filename[MAX_PATH]; -int new_font=-1; -int font_force; -int setfont_return; -pthread_mutex_t copybuf_mutex; -pthread_mutex_t lines_mutex; -char *copybuf=NULL; -char *pastebuf=NULL; -sem_t x11_beep; -sem_t x11_title; -sem_t x11_name; -int InitCS; -int InitCE; -int FW, FH; -int FontScale=1; -#define MAX_SCALE 2 -WORD DpyCols=80; /* Initialize this so init_mode() is happy */ -BYTE DpyRows; -BYTE *palette; -BYTE CursStart; -BYTE CursEnd; -WORD *vmem=NULL; -static int show = 1; -BYTE CursRow=0; -BYTE CursCol=0; -static int x_current_font=-99; -typedef struct TextLine { - WORD *data; - u_char max_length; /* Not used, but here for future use */ - u_char *exposed; -} TextLine; -TextLine *lines = NULL; -unsigned int x_pending_mousekeys=0; - -/* X Variables */ -Display *dpy=NULL; -Window win; -XImage *xi = 0; -Pixmap pfnt=0; -Visual *visual; -unsigned int depth; -unsigned long black; -unsigned long white; -GC gc; -GC cgc; -int xfd; -char window_title[81]; -char window_name[81]; - -int x11_window_xpos=-1; -int x11_window_ypos=-1; -int x11_window_width=-1; -int x11_window_height=-1; - -/* X functions */ -struct x11 { - int (*XChangeGC) (Display*, GC, unsigned long, XGCValues*); - int (*XCopyPlane) (Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); - int (*XFillRectangle) (Display*, Drawable, GC, int, int, unsigned int, unsigned int); - int (*XFlush) (Display*); - int (*XBell) (Display*, int); - int (*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*); - int (*XNextEvent) (Display*, XEvent *); - XSizeHints* (*XAllocSizeHints)(void); - void (*XSetWMNormalHints) (Display*, Window, XSizeHints*); - int (*XResizeWindow)(Display*, Window, unsigned int, unsigned int); - int (*XMapWindow) (Display*, Window); - int (*XFree) (void *data); - int (*XFreePixmap) (Display*, Pixmap); - Pixmap (*XCreateBitmapFromData) (Display*, Drawable, _Xconst char*, unsigned int, unsigned int); - Status (*XAllocColor) (Display*, Colormap, XColor*); - Display*(*XOpenDisplay) (_Xconst char*); - Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); - GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*); - int (*XSelectInput) (Display*, Window, long); - int (*XStoreName) (Display*, Window, _Xconst char*); - Window (*XGetSelectionOwner) (Display*, Atom); - int (*XConvertSelection) (Display*, Atom, Atom, Atom, Window, Time); - int (*XGetWindowProperty) (Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **); - int (*XChangeProperty) (Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int); - Status (*XSendEvent) (Display*, Window, Bool, long, XEvent*); - int (*XSetSelectionOwner) (Display*, Atom, Window, Time); - int (*XSetIconName) (Display*, Window, _Xconst char *); -}; -struct x11 x11; - -/* X pixel values for the RGB triples */ -DWORD pixels[16]; - -static fd_set fdset; /* File Descriptors to select on */ - -/* Keyboard stuff */ -WORD keybuf[0x25]; -#define K_NEXT keybuf[0x21] /* *(WORD *)0x41a */ -#define K_FREE keybuf[0x22] /* *(WORD *)0x41c */ -#define K_BUFSTARTP keybuf[0x23] /* *(WORD *)0x480 */ -#define K_BUFENDP keybuf[0x24] /* *(WORD *)0x482 */ -#define K_BUFSTART (&keybuf[K_BUFSTARTP]) /* ((WORD *)(0x400 + K_BUFSTARTP)) */ -#define K_BUFEND (&keybuf[K_BUFENDP]) /* ((WORD *)(0x400 + keybuf[3])) */ -#define K_BUF(i) keybuf[i] /* *((WORD *)((u_char *)0x400 + (i))) */ - -BYTE K1_STATUS; -#define K1_RSHIFT 0x01 -#define K1_LSHIFT 0x02 -#define K1_SHIFT 0x03 -#define K1_CTRL 0x04 -#define K1_ALT 0x08 -#define K1_SLOCK 0x10 /* Active */ -#define K1_NLOCK 0x20 /* Active */ -#define K1_CLOCK 0x40 /* Active */ -#define K1_INSERT 0x80 /* Active */ - -BYTE K2_STATUS; -#define K2_LCTRL 0x01 -#define K2_LALT 0x02 -#define K2_SYSREQ 0x04 -#define K2_PAUSE 0x08 -#define K2_SLOCK 0x10 /* Actually held down */ -#define K2_NLOCK 0x20 /* Actually held down */ -#define K2_CLOCK 0x40 /* Actually held down */ -#define K2_INSERT 0x80 /* Actually held down */ - -BYTE K3_STATUS; -#define K3_E1 0x01 /* Last code read was e1 */ -#define K3_E2 0x02 /* Last code read was e2 */ -#define K3_RCTRL 0x04 -#define K3_RALT 0x08 -#define K3_ENHANCED 0x10 -#define K3_FORCENLOCK 0x20 -#define K3_TWOBYTE 0x40 /* last code was first of 2 */ -#define K3_READID 0x80 /* read ID in progress */ - -BYTE K4_STATUS; -#define K4_SLOCK_LED 0x01 -#define K4_NLOCK_LED 0x02 -#define K4_CLOCK_LED 0x04 -#define K4_ACK 0x10 /* ACK recieved from keyboard */ -#define K4_RESEND 0x20 /* RESEND recieved from keyboard */ -#define K4_LED 0x40 /* LED update in progress */ -#define K4_ERROR 0x80 - -int flipdelete = 0; /* Flip meaning of delete and backspace */ -static WORD break_code = 0x00; - -static WORD Ascii2Scan[] = { - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, - 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028, - 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035, - 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, - 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135, - 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122, - 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118, - 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111, - 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c, - 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022, - 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018, - 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011, - 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff, -}; - -struct { - WORD base; - WORD shift; - WORD ctrl; - WORD alt; -} ScanCodes[] = { - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */ - { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */ - { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */ - { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */ - { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */ - { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */ - { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */ - { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */ - { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */ - { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */ - { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */ - { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */ - { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */ - { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */ - { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */ - { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */ - { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */ - { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */ - { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */ - { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */ - { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */ - { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */ - { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */ - { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */ - { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */ - { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */ - { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */ - { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */ - { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */ - { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */ - { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */ - { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */ - { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */ - { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */ - { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */ - { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */ - { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */ - { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */ - { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */ - { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */ - { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */ - { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */ - { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */ - { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */ - { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */ - { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */ - { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */ - { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */ - { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */ - { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */ - { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */ - { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */ - { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */ - { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */ - { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */ - { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */ - { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */ - { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */ - { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */ - { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */ - { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */ - { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */ - { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */ - { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */ - { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */ - { 0x4800, 0x4838, 0x8d00, 0x9800 }, /* key 72 - cursor up */ - { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */ - { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */ - { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */ - { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */ - { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */ - { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */ - { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */ - { 0x5000, 0x5032, 0x9100, 0xa000 }, /* key 80 - cursor down */ - { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */ - { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */ - { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */ - { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */ - { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */ - { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */ -}; - -#define HWM 16 -void resize_window(void); -int KbdEmpty(void); -int load_font(char *filename, int width, int height, int scale, int *newmode); - -void tty_pause() -{ - usleep(1000); -} - -volatile int poll_cnt = 0; - -void -wakeup_poll(void) -{ - if (poll_cnt <= 0) - poll_cnt = HWM; -} - -void -reset_poll(void) -{ - poll_cnt = HWM; -} - -void -sleep_poll(void) -{ - if (--poll_cnt <= 0) { - poll_cnt = 0; - while (KbdEmpty() && poll_cnt <= 0) { - if (KbdEmpty() && poll_cnt <= 0) - tty_pause(); - } - } -} - -static void -setgc(WORD attr) -{ - XGCValues v; - - v.background = pixels[(attr >> 12) & 0x07]; - if ((!show) && (attr & 0x8000)) - v.foreground = v.background; - else - v.foreground = pixels[(attr >> 8) & 0x0f]; - - x11.XChangeGC(dpy, gc, GCForeground|GCBackground, &v); -} - -static void -video_update_text() -{ - static int or = -1; - static int oc = -1; - static int os = -1; - - static char buf[256]; - int r, c; - int attr; - XGCValues v; - WORD *vmemc; - int cursrow; - int curscol; - int flush=0; - - cursrow=CursRow; - curscol=CursCol; - wakeup_poll(); /* Wake up anyone waiting on kbd poll */ - - vmemc = (WORD *)alloca(DpyCols*(DpyRows+1)*sizeof(WORD)); - pthread_mutex_lock(&lines_mutex); - memcpy(vmemc, vmem, DpyCols*(DpyRows+1)*sizeof(WORD)); - for (r = 0; r < (DpyRows+1); ++r) { - for (c = 0; c < DpyCols; ++c) { - if ((lines[r].data[c] != vmemc[r * DpyCols + c]) - || (lines[r].data[c] & 0x8000 && show != os) - || (lines[r].exposed[c]) - || (((r == or && c==oc) || (r == cursrow && c==curscol)) && (or != cursrow || oc !=curscol))) { - setgc(vmemc[r * DpyCols + c] & 0xff00); - x11.XCopyPlane(dpy,pfnt,win,gc,0,FH*(vmemc[r * DpyCols + c]&0xff),FW,FH,c*FW+2,r*FH+2,1); - lines[r].exposed[c]=0; - lines[r].data[c]=vmemc[r * DpyCols + c]; - flush=1; - } - } - - reset_poll(); - } - pthread_mutex_unlock(&lines_mutex); - - if (CursStart <= CursEnd && CursEnd <= FH && - (show != os) && cursrow < (DpyRows+1) &&curscol < DpyCols) { - - attr = vmemc[cursrow * DpyCols +curscol] & 0xff00; - v.foreground = pixels[(attr >> 8) & 0x0f] ^ - pixels[(attr >> 12) & 0x07]; - if (v.foreground) { - v.function = GXxor; - } else { - v.foreground = pixels[7]; - v.function = GXcopy; - } - x11.XChangeGC(dpy, cgc, GCForeground | GCFunction, &v); - x11.XFillRectangle(dpy, win, cgc, - 2 +curscol * FW, - 2 + cursrow * FH + CursStart * FontScale, - FW, (CursEnd + 1)*FontScale - (CursStart*FontScale)); - flush=1; - } - - or =cursrow; - oc =curscol; - os =show; - if(flush) - x11.XFlush(dpy); -} - -void -video_update() -{ - static clock_t lastupd=-1; - static int clock_started=0; - clock_t upd; - - upd=msclock(); - if(!clock_started) { - lastupd=upd; - clock_started=1; - } - if(upd-lastupd>(MSCLOCKS_PER_SEC/2)) { - show ^= 1; - lastupd=upd; - } - - /* quick and dirty */ - video_update_text(); -} - -/* Get memory for the text line buffer. */ -void -get_lines() -{ - int i; - TextLine *newlines; - - if (lines == NULL) { - pthread_mutex_lock(&lines_mutex); - lines = (TextLine *)malloc(sizeof(TextLine) * (CONSOLE_MAX_ROWS+1)); - if (lines == NULL) { - fprintf(stderr, "Could not allocate data structure for text lines\n"); - exit(1); - } - for (i = 0; i < (CONSOLE_MAX_ROWS+1); ++i) { - lines[i].max_length = DpyCols; - lines[i].data = (WORD *)malloc(CONSOLE_MAX_COLS * sizeof(WORD)); - if (lines[i].data == NULL) { - fprintf(stderr, "Could not allocate data structure for text lines\n"); - exit(1); - } - lines[i].exposed = (u_char *)malloc(CONSOLE_MAX_COLS * sizeof(u_char)); - if (lines[i].exposed == NULL) { - fprintf(stderr, "Could not allocate data structure for text lines\n"); - exit(1); - } - memset(lines[i].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char)); - } - pthread_mutex_unlock(&lines_mutex); - } -} - -void -KbdWrite(WORD code) -{ - int kf; - - kf = K_FREE + 2; - if (kf == K_BUFENDP) - kf = K_BUFSTARTP; - - if (kf == K_NEXT) { - if(code==CIO_KEY_MOUSE) - x_pending_mousekeys++; - else { - x11.XBell(dpy, 0); - return; - } - } - K_BUF(K_FREE) = code; - K_FREE = kf; -} - -void tty_beep(void) -{ - sem_post(&x11_beep); -} - -void expose_chars(int x, int y, int width, int height) -{ - int sx,sy,ex,ey; - int r,c; - - sx=x; - sx-=2; - if(sx<0) - sx=0; - sy=y; - sy-=2; - if(sy<0) - sy=0; - ex=sx+width+FW-1; - ey=sy+height+FH-1; - sx/=FW; - ex/=FW; - if(ex>=DpyCols) - ex=DpyCols-1; - sy/=FH; - ey/=FH; - if(ey>DpyRows) - ey=DpyRows; - - for(r=sy;r<=ey;r++) { - pthread_mutex_lock(&lines_mutex); - for(c=sx;c<=ex;c++) { - lines[r].exposed[c]=1; - } - pthread_mutex_unlock(&lines_mutex); - } -} - -static int -video_event(XEvent *ev) -{ - switch (ev->type) { - case ConfigureNotify: { - int newFSH=1; - int newFSW=1; - int oldFS; - int r; - - oldFS=FontScale; - x11_window_xpos=ev->xconfigure.x-ev->xconfigure.border_width; - x11_window_ypos=ev->xconfigure.y-ev->xconfigure.border_width; - x11_window_width=ev->xconfigure.width+ev->xconfigure.border_width*2; - x11_window_height=ev->xconfigure.height+ev->xconfigure.border_width*2; - if((ev->xconfigure.width == FW * DpyCols + 4) - && (ev->xconfigure.height == FH * (DpyRows+1) + 4)) - break; - - FW=FW/FontScale; - FH=FH/FontScale; - newFSH=(ev->xconfigure.width+(FW*DpyCols)/2)/(FW*DpyCols); - newFSW=(ev->xconfigure.height+(FH*(DpyRows+1))/2)/(FH*(DpyRows+1)); - if(newFSW<1) - newFSW=1; - if(newFSW>MAX_SCALE) - newFSW=MAX_SCALE; - if(newFSH<1) - newFSH=1; - if(newFSH>MAX_SCALE) - newFSH=MAX_SCALE; - if(newFSH<newFSW) - FontScale=newFSH; - else - FontScale=newFSW; - load_font(NULL,FW,FH,FontScale,NULL); - resize_window(); - break; - } - case SelectionClear: { - XSelectionClearEvent *req; - - req=&(ev->xselectionclear); - pthread_mutex_lock(©buf_mutex); - if(req->selection==CONSOLE_CLIPBOARD && copybuf!=NULL) { - free(copybuf); - copybuf=NULL; - } - pthread_mutex_unlock(©buf_mutex); - break; - } - case SelectionNotify: { - int format; - unsigned long len, bytes_left, dummy; - Atom type; - - if(ev->xselection.requestor!=win) - break; - x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf)); - if(bytes_left > 0 && format==8) - x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf); - else - pastebuf=NULL; - - /* Set paste buffer */ - sem_post(&pastebuf_set); - sem_wait(&pastebuf_request); - x11.XFree(pastebuf); - pastebuf=NULL; - break; - } - case SelectionRequest: { - XSelectionRequestEvent *req; - XEvent respond; - - req=&(ev->xselectionrequest); - pthread_mutex_lock(©buf_mutex); - if(copybuf==NULL) { - respond.xselection.property=None; - } - else { - if(req->target==XA_STRING) { - x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf)); - respond.xselection.property=req->property; - } - else - respond.xselection.property=None; - } - respond.xselection.type=SelectionNotify; - respond.xselection.display=req->display; - respond.xselection.requestor=req->requestor; - respond.xselection.selection=req->selection; - respond.xselection.target=req->target; - respond.xselection.time=req->time; - x11.XSendEvent(dpy,req->requestor,0,0,&respond); - pthread_mutex_unlock(©buf_mutex); - break; - } - case MotionNotify: { - XMotionEvent *me = (XMotionEvent *)ev; - me->x -= 2; - me->y -= 2; - me->x/=FW; - me->y/=FH; - me->x++; - me->y++; - if(me->x<1) - me->x=1; - if(me->y<1) - me->y=1; - if(me->x>DpyCols) - me->x=DpyCols; - if(me->y>DpyRows+1) - me->y=DpyRows+1; - ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y); - break; - } - case ButtonRelease: { - XButtonEvent *be = (XButtonEvent *)ev; - be->x -= 2; - be->y -= 2; - be->x/=FW; - be->y/=FH; - be->x++; - be->y++; - if(be->x<1) - be->x=1; - if(be->y<1) - be->y=1; - if(be->x>DpyCols) - be->x=DpyCols; - if(be->y>DpyRows+1) - be->y=DpyRows+1; - if (be->button <= 3) { - ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y); - } - break; - } - case ButtonPress: { - XButtonEvent *be = (XButtonEvent *)ev; - be->x -= 2; - be->y -= 2; - be->x/=FW; - be->y/=FH; - be->x++; - be->y++; - if(be->x<1) - be->x=1; - if(be->y<1) - be->y=1; - if(be->x>DpyCols) - be->x=DpyCols; - if(be->y>DpyRows+1) - be->y=DpyRows+1; - if (be->button <= 3) { - ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y); - } - break; - } - case NoExpose: - break; - case GraphicsExpose: { - expose_chars(ev->xgraphicsexpose.x,ev->xgraphicsexpose.y - ,ev->xgraphicsexpose.width,ev->xgraphicsexpose.height); - break; - } - case Expose: { - expose_chars(ev->xexpose.x,ev->xexpose.y,ev->xexpose.width,ev->xexpose.height); - break; - } - case KeyRelease: { - static char buf[128]; - KeySym ks; - - break_code |= 0x80; - - if (!(ev->xkey.state & ShiftMask)) { - K1_STATUS &= ~K1_LSHIFT; - K1_STATUS &= ~K1_RSHIFT; - } - if (!(ev->xkey.state & ControlMask)) { - K1_STATUS &= ~K1_CTRL; - K2_STATUS &= ~K2_LCTRL; - K3_STATUS &= ~K3_RCTRL; - } - if (!(ev->xkey.state & Mod1Mask)) { - K1_STATUS &= ~K1_ALT; - K2_STATUS &= ~K2_LALT; - K3_STATUS &= ~K3_RALT; - } - if (!(ev->xkey.state & LockMask)) { - K2_STATUS &= ~K2_CLOCK; - } - - x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0); - switch (ks) { - case XK_Shift_L: - K1_STATUS &= ~K1_LSHIFT; - break; - case XK_Shift_R: - K1_STATUS &= ~K1_RSHIFT; - break; - case XK_Control_L: - K1_STATUS &= ~K1_CTRL; - K2_STATUS &= ~K2_LCTRL; - break; - case XK_Control_R: - K1_STATUS &= ~K1_CTRL; - K3_STATUS &= ~K3_RCTRL; - break; - case XK_Alt_L: - K1_STATUS &= ~K1_ALT; - K2_STATUS &= ~K2_LALT; - break; - case XK_Alt_R: - K1_STATUS &= ~K1_ALT; - K3_STATUS &= ~K3_RALT; - break; - case XK_Scroll_Lock: - K2_STATUS &= ~K2_SLOCK; - break; - case XK_Num_Lock: - K2_STATUS &= ~K2_NLOCK; - break; - case XK_Caps_Lock: - K2_STATUS &= ~K2_CLOCK; - break; - case XK_Insert: - K2_STATUS &= ~K2_INSERT; - break; - } - return(1); - } - case KeyPress: { - static char buf[128]; - KeySym ks; - int n; - int nlock = 0; - WORD scan = 0xffff; - - if (!(ev->xkey.state & ShiftMask)) { - K1_STATUS &= ~K1_LSHIFT; - K1_STATUS &= ~K1_RSHIFT; - } - if (!(ev->xkey.state & ControlMask)) { - K1_STATUS &= ~K1_CTRL; - K2_STATUS &= ~K2_LCTRL; - K3_STATUS &= ~K3_RCTRL; - } - if (!(ev->xkey.state & Mod1Mask)) { - K1_STATUS &= ~K1_ALT; - K2_STATUS &= ~K2_LALT; - K3_STATUS &= ~K3_RALT; - } - if (!(ev->xkey.state & LockMask)) { - K2_STATUS &= ~K2_CLOCK; - } - - n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0); - - switch (ks) { - case XK_Shift_L: - K1_STATUS |= K1_LSHIFT; - break; - case XK_Shift_R: - K1_STATUS |= K1_RSHIFT; - break; - case XK_Control_L: - K1_STATUS |= K1_CTRL; - K2_STATUS |= K2_LCTRL; - break; - case XK_Control_R: - K1_STATUS |= K1_CTRL; - K3_STATUS |= K3_RCTRL; - break; - case XK_Alt_L: - K1_STATUS |= K1_ALT; - K2_STATUS |= K2_LALT; - break; - case XK_Alt_R: - K1_STATUS |= K1_ALT; - K3_STATUS |= K3_RALT; - break; - case XK_Scroll_Lock: - K1_STATUS ^= K1_SLOCK; - K2_STATUS |= K2_SLOCK; - break; - case XK_Num_Lock: - K1_STATUS ^= K1_NLOCK; - K2_STATUS |= K2_NLOCK; - break; - case XK_Caps_Lock: - K1_STATUS ^= K1_CLOCK; - K2_STATUS |= K2_CLOCK; - break; - case XK_Insert: - case XK_KP_Insert: - K1_STATUS ^= K1_INSERT; - K2_STATUS |= K2_INSERT; - scan = 82; - goto docode; - - case XK_Escape: - scan = 1; - goto docode; - - case XK_Tab: - case XK_ISO_Left_Tab: - scan = 15; - goto docode; - - case XK_Return: - case XK_KP_Enter: - scan = 28; - goto docode; - - case XK_Print: - scan = 55; - goto docode; - - case XK_F1: - case XK_F2: - case XK_F3: - case XK_F4: - case XK_F5: - case XK_F6: - case XK_F7: - case XK_F8: - case XK_F9: - case XK_F10: - scan = ks - XK_F1 + 59; - goto docode; - - case XK_KP_7: - nlock = 1; - case XK_Home: - case XK_KP_Home: - scan = 71; - goto docode; - case XK_KP_8: - nlock = 1; - case XK_Up: - case XK_KP_Up: - scan = 72; - goto docode; - case XK_KP_9: - nlock = 1; - case XK_Prior: - case XK_KP_Prior: - scan = 73; - goto docode; - case XK_KP_Subtract: - scan = 74; - goto docode; - case XK_KP_4: - nlock = 1; - case XK_Left: - case XK_KP_Left: - scan = 75; - goto docode; - case XK_KP_5: - nlock = 1; - case XK_Begin: - case XK_KP_Begin: - scan = 76; - goto docode; - case XK_KP_6: - nlock = 1; - case XK_Right: - case XK_KP_Right: - scan = 77; - goto docode; - case XK_KP_Add: - scan = 78; - goto docode; - case XK_KP_1: - nlock = 1; - case XK_End: - case XK_KP_End: - scan = 79; - goto docode; - case XK_KP_2: - nlock = 1; - case XK_Down: - case XK_KP_Down: - scan = 80; - goto docode; - case XK_KP_3: - nlock = 1; - case XK_Next: - case XK_KP_Next: - scan = 81; - goto docode; - case XK_KP_0: - nlock = 1; - /* case XK_Insert: This is above */ - scan = 82; - goto docode; - - case XK_KP_Decimal: - nlock = 1; - scan = 83; - goto docode; - - case XK_Delete: - case XK_KP_Delete: - scan = flipdelete ? 14 : 83; - goto docode; - - case XK_BackSpace: - scan = flipdelete ? 83 : 14; - goto docode; - - case XK_F11: - scan = 87; - goto docode; - case XK_F12: - scan = 88; - goto docode; - - - case XK_KP_Divide: - scan = Ascii2Scan['/']; - goto docode; - - case XK_KP_Multiply: - scan = Ascii2Scan['*']; - goto docode; - - default: - if (ks < ' ' || ks > '~') - break; - scan = Ascii2Scan[ks]; - docode: - if (nlock) - scan |= 0x100; - - if ((scan & ~0x100) > 88) { - scan = 0xffff; - break; - } - - if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) { - scan = ScanCodes[scan & 0xff].shift; - } else if (K1_STATUS & K1_CTRL) { - scan = ScanCodes[scan & 0xff].ctrl; - } else if (K1_STATUS & K1_ALT) { - scan = ScanCodes[scan & 0xff].alt; - } else - scan = ScanCodes[scan & 0xff].base; - - break; - } - if (scan != 0xffff) { - break_code = scan >> 8; - KbdWrite(scan); - } - return(1); - } - - default: - break; - } - return(0); -} - -void -mouse_event(void *crap) -{ - while(1) { - if(mouse_wait()) - KbdWrite(CIO_KEY_MOUSE); - } -} - -void -video_async_event(void *crap) -{ - int x; - fd_set fdset; - XEvent ev; - static struct timeval tv; - - for (;;) { - video_update(); - - tv.tv_sec=0; - tv.tv_usec=54925; - /* - * Handle any events just sitting around... - */ - while (QLength(dpy) > 0) { - x11.XNextEvent(dpy, &ev); - video_event(&ev); - } - - FD_ZERO(&fdset); - FD_SET(xfd, &fdset); - - x = select(xfd+1, &fdset, 0, 0, &tv); - - switch (x) { - case -1: - /* - * Errno might be wrong, so we just select again. - * This could cause a problem is something really - * was wrong with select.... - */ - - /* perror("select"); */ - break; - case 0: - if(console_new_mode!=NO_NEW_MODE) - init_mode(console_new_mode); - if(x_current_font!=new_font) { - int oldfont=x_current_font; - int newmode=0; - - x_current_font=new_font; - if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,&newmode)) { - if(font_force && newmode) { - init_mode(newmode); - sem_wait(&console_mode_changed); - if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL)) { - setfont_return=-1; - x_current_font=oldfont; - new_font=oldfont; - load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL); - } - else - setfont_return=0; - } - else { - setfont_return=-1; - x_current_font=oldfont; - new_font=oldfont; - load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL); - } - } - else - setfont_return=0; - resize_window(); - sem_post(&font_set); - } - while(!sem_trywait(&x11_beep)) - x11.XBell(dpy, 0); - if(!sem_trywait(&x11_name)) - x11.XSetIconName(dpy, win, window_name); - if(!sem_trywait(&x11_loadfont)) { - int oldfont=x_current_font; - x_load_font_ret=load_font(font_filename,FW/FontScale,FH/FontScale,FontScale,NULL); - if(x_load_font_ret) - x_current_font=oldfont; - new_font=x_current_font; - resize_window(); - sem_post(&x11_fontloaded); - } - if(!sem_trywait(&x11_title)) - x11.XStoreName(dpy, win, window_title); - if(!sem_trywait(©buf_set)) { - /* Copybuf has been set and isn't NULL */ - x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime); - } - if(!sem_trywait(&pastebuf_request)) { - Window sowner=None; - - sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD); - if(sowner==win) { - /* Get your own primary selection */ - if(copybuf==NULL) - pastebuf=NULL; - else - pastebuf=(unsigned char *)malloc(strlen(copybuf)+1); - if(pastebuf!=NULL) - strcpy(pastebuf,copybuf); - /* Set paste buffer */ - sem_post(&pastebuf_set); - sem_wait(&pastebuf_request); - if(pastebuf!=NULL) - free(pastebuf); - pastebuf=NULL; - } - else if(sowner!=None) { - x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, None, win, CurrentTime); - } - else { - /* Set paste buffer */ - pastebuf=NULL; - sem_post(&pastebuf_set); - sem_wait(&pastebuf_request); - } - } - break; - default: - if (FD_ISSET(xfd, &fdset)) { - do { - x11.XNextEvent(dpy, &ev); - video_event(&ev); - } while (QLength(dpy)); - } - } - } -} - -/* Resize the window, using information from 'vga_status[]'. This function is - called after a mode change. */ -void -resize_window() -{ - XSizeHints *sh; - int r; - - sh = x11.XAllocSizeHints(); - if (sh == NULL) { - fprintf(stderr, "Could not get XSizeHints structure"); - exit(1); - } - - sh->base_width = FW * DpyCols + 4; - sh->base_height = FH * (DpyRows+1) + 4; - - sh->min_width = (FW/FontScale) * DpyCols + 4; - sh->max_width = (FW/FontScale) * MAX_SCALE * DpyCols + 4; - sh->min_height = (FH/FontScale) * (DpyRows+1) +4; - sh->max_height = (FH/FontScale) * MAX_SCALE * (DpyRows+1) +4; - sh->flags = USSize | PMinSize | PMaxSize | PSize; - - x11.XSetWMNormalHints(dpy, win, sh); - x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height); - x11.XMapWindow(dpy, win); - - x11.XFree(sh); - - if(lines != NULL) { - pthread_mutex_lock(&lines_mutex); - for (r = 0; r < (CONSOLE_MAX_ROWS+1); ++r) { - memset(lines[r].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char)); - } - pthread_mutex_unlock(&lines_mutex); - } - - return; -} - -/* Scales a bitmap up to 2x it's current size */ -char * -scale_bitmap(char *bitmap, int width, int height, int *multiplier) -{ - char *ret; - char *outbyte; - int pos; - int origbmpsize; - int origbytesperline=1; - int scaledbmpsize; - int scaledbytesperline=1; - - while(origbytesperline*8<width) - origbytesperline++; - - if(*multiplier>MAX_SCALE) - *multiplier=MAX_SCALE; - if(*multiplier < 1) - *multiplier=1; - while(scaledbytesperline * 8<width*(*multiplier)) - scaledbytesperline++; - - origbmpsize=origbytesperline*height; - scaledbmpsize=scaledbytesperline*height*(*multiplier); - - ret=(char *)malloc(scaledbmpsize); - if(ret==NULL) - return(NULL); - outbyte=ret; - for(pos=0;pos<origbmpsize;pos++) { - switch(*multiplier) { - case 1: - *(outbyte++)=bitmap[pos]; - break; - case 2: - *outbyte= - ((bitmap[pos]&0x08)<<4) - |((bitmap[pos]&0x08)<<3) - |((bitmap[pos]&0x04)<<3) - |((bitmap[pos]&0x04)<<2) - |((bitmap[pos]&0x02)<<2) - |((bitmap[pos]&0x02)<<1) - |((bitmap[pos]&0x01)<<1) - |((bitmap[pos]&0x01)); - outbyte++; - *outbyte= - ((bitmap[pos]&0x80)) - |((bitmap[pos]&0x80)>>1) - |((bitmap[pos]&0x40)>>1) - |((bitmap[pos]&0x40)>>2) - |((bitmap[pos]&0x20)>>2) - |((bitmap[pos]&0x20)>>3) - |((bitmap[pos]&0x10)>>3) - |((bitmap[pos]&0x10)>>4); - outbyte++; - *outbyte= - ((bitmap[pos]&0x08)<<4) - |((bitmap[pos]&0x08)<<3) - |((bitmap[pos]&0x04)<<3) - |((bitmap[pos]&0x04)<<2) - |((bitmap[pos]&0x02)<<2) - |((bitmap[pos]&0x02)<<1) - |((bitmap[pos]&0x01)<<1) - |((bitmap[pos]&0x01)); - outbyte++; - *outbyte= - ((bitmap[pos]&0x80)) - |((bitmap[pos]&0x80)>>1) - |((bitmap[pos]&0x40)>>1) - |((bitmap[pos]&0x40)>>2) - |((bitmap[pos]&0x20)>>2) - |((bitmap[pos]&0x20)>>3) - |((bitmap[pos]&0x10)>>3) - |((bitmap[pos]&0x10)>>4); - outbyte++; - break; - } - } - return(ret); -} - -/* No longer uses X fonts - pass NULL to use VGA 8x16 font */ -int -load_font(char *filename, int width, int height, int scale, int *newmode) -{ - XGCValues gcv; - char *font; - char *scaledfont; - char fontdata[256*16]; - int i,j; - static char current_filename[MAX_PATH]; - FILE *fontfile; - - if(height > 16) - return(-1); - - if(x_current_font==-99 || x_current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) { - for(i=0; conio_fontdata[i].desc != NULL; i++) { - if(!strcmp(conio_fontdata[i].desc, "Codepage 437 English")) { - x_current_font=i; - break; - } - } - if(conio_fontdata[i].desc==NULL) - x_current_font=0; - new_font=x_current_font; - } - if(x_current_font==-1) - filename=current_filename; - else if(conio_fontdata[x_current_font].desc==NULL) - return(-1); - - if(filename != NULL) { - int fl=flength(filename); - - if(newmode != NULL) { - switch(fl/256) { - case 8: - *newmode=C80X50; - break; - case 14: - *newmode=C80X28; - break; - case 16: - *newmode=C80; - break; - } - } - if(fl!=height*256) - return(-1); - if((fontfile=fopen(filename,"rb"))==NULL) - return(-1); - if(fread(fontdata, 1, height*256, fontfile)!=height*256) { - fclose(fontfile); - return(-1); - } - fclose(fontfile); - x_current_font=new_font=-1; - if(filename != current_filename) - SAFECOPY(current_filename,filename); - } - else { - if(newmode != NULL) { - if(conio_fontdata[x_current_font].eight_by_sixteen!=NULL) - *newmode=C80; - else if(conio_fontdata[x_current_font].eight_by_fourteen!=NULL) - *newmode=C80X28; - else if(conio_fontdata[x_current_font].eight_by_eight!=NULL) - *newmode=C80X50; - } - switch(width) { - case 8: - switch(height) { - case 8: - font=conio_fontdata[x_current_font].eight_by_eight; - break; - case 14: - font=conio_fontdata[x_current_font].eight_by_fourteen; - break; - case 16: - font=conio_fontdata[x_current_font].eight_by_sixteen; - break; - default: - return(1); - } - break; - default: - return(1); - } - if(font==NULL) - return(1); - memcpy(fontdata, font, height*256); - } - FW = width; - FH = height; - /* Swap bit order... leftmost bit is most significant, X11 wants it the - * other way. */ - for(i=0; i<256; i++) { - for(j=0; j<height; j++) { - fontdata[i*height+j]= ((fontdata[i*height+j] & 0x80) >> 7) - | ((fontdata[i*height+j] & 0x40) >> 5) - | ((fontdata[i*height+j] & 0x20) >> 3) - | ((fontdata[i*height+j] & 0x10) >> 1) - | ((fontdata[i*height+j] & 0x08) << 1) - | ((fontdata[i*height+j] & 0x04) << 3) - | ((fontdata[i*height+j] & 0x02) << 5) - | ((fontdata[i*height+j] & 0x01) << 7); - } - } - if(pfnt!=0) - x11.XFreePixmap(dpy,pfnt); - scaledfont=scale_bitmap(fontdata, FW, FH*256, &FontScale); - if(scaledfont==NULL) - pfnt=x11.XCreateBitmapFromData(dpy, win, fontdata, FW, FH*256); - else { - FW*=scale; - FH*=scale; - pfnt=x11.XCreateBitmapFromData(dpy, win, scaledfont, FW, FH*256); - free(scaledfont); - } - - return(0); -} - -/* Calculate 'pixels[]' from the current DAC table and palette. - - To do: do not use 'pixels[]', use an array of 'XColor's which we can - allocate and free on demand. Install a private colormap if necessary. */ -void -update_pixels() -{ - int i; - Colormap cm; - - /* We support only 16 colors for now. */ - for (i = 0; i < 16; i++) { - XColor color; - - color.red = dac_default[palette[i]].red << 8; - color.green = dac_default[palette[i]].green << 8; - color.blue = dac_default[palette[i]].blue << 8; - if (x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) { - pixels[i] = color.pixel; - } else if (i < 7) - pixels[i] = BlackPixel(dpy, DefaultScreen(dpy)); - else - pixels[i] = WhitePixel(dpy, DefaultScreen(dpy)); - } -} - -int -init_mode(int mode) -{ - struct video_params vmode; - int idx; /* Index into vmode */ - int i; - WORD oldcols = DpyCols; - - idx = find_vmode(mode); - if (idx == -1) { - console_new_mode=NO_NEW_MODE; - sem_post(&console_mode_changed); - return(-1); - } - vmode = vparams[idx]; - - DpyCols = vmode.cols; - CursStart = vmode.curs_start; - CursEnd = vmode.curs_end; - DpyRows = vmode.rows-1; - InitCS = CursStart; - InitCE = CursEnd; - - vmem = (WORD *)realloc(vmem,vmode.cols*vmode.rows*sizeof(WORD)); - /* Deal with 40 col doubling */ - if(oldcols != DpyCols) { - if(oldcols == 40) - FontScale /= 2; - if(DpyCols == 40) - FontScale *= 2; - } - - if(FontScale > MAX_SCALE) - FontScale = MAX_SCALE; - - if(FontScale < 1) - FontScale = 1; - - /* Point 'palette[]' to the Attribute Controller space. We will only use - the first 16 slots. */ - palette = palettes[vmode.palette]; - - /* Load 'pixels[]' from default DAC values. */ - update_pixels(); - - /* Update font. */ - if(load_font(NULL,vmode.charwidth,vmode.charheight,FontScale,NULL)) { - sem_post(&console_mode_changed); - return(-1); - } - - /* Resize window if necessary. */ - resize_window(); - - get_lines(); - - /* Initialize video memory with black background, white foreground */ - for (i = 0; i < DpyCols*DpyRows; ++i) - vmem[i] = 0x0700; - - CurrMode=mode; - console_new_mode=NO_NEW_MODE; - - cio_textinfo.attribute=7; - cio_textinfo.normattr=7; - cio_textinfo.currmode=mode; - cio_textinfo.screenheight=DpyRows+1; - cio_textinfo.screenwidth=DpyCols; - cio_textinfo.curx=1; - cio_textinfo.cury=1; - cio_textinfo.winleft=1; - cio_textinfo.wintop=1; - cio_textinfo.winright=cio_textinfo.screenwidth; - cio_textinfo.winbottom=cio_textinfo.screenheight; - - sem_post(&console_mode_changed); - return(0); -} - -/* Get a connection to the X server and create the window. */ -int -init_window() -{ - XGCValues gcv; - int i; - - dpy = x11.XOpenDisplay(NULL); - if (dpy == NULL) { - return(-1); - } - xfd = ConnectionNumber(dpy); - - /* Create window, but defer setting a size and GC. */ - win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, - 1, 1, 2, black, black); - - gcv.foreground = white; - gcv.background = black; - gc = x11.XCreateGC(dpy, win, GCForeground | GCBackground, &gcv); - - gcv.foreground = 1; - gcv.background = 0; - gcv.function = GXxor; - cgc = x11.XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv); - - x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask | - ExposureMask | ButtonPressMask - | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask); - - SAFECOPY(window_title,"SyncConsole"); - x11.XStoreName(dpy, win, window_title); - - /* Get the default visual and depth for later use. */ - depth = DefaultDepth(dpy, DefaultScreen(dpy)); - visual = DefaultVisual(dpy, DefaultScreen(dpy)); - - return(0); -} - -int -kbd_init() -{ - K_BUFSTARTP = 0x0000; /* Start of keyboard buffer */ - K_BUFENDP = 0x20; /* End of keyboard buffer */ - K_NEXT = K_FREE = K_BUFSTARTP; - - return(0); -} - -int -console_init() -{ - int fd; - int i; - void *dl; - - if(dpy!=NULL) - return(0); - -#ifdef STATIC_LINK - x11.XChangeGC=XChangeGC; - x11.XCopyPlane=XCopyPlane; - x11.XFillRectangle=XFillRectangle; - x11.XFlush=XFlush; - x11.XBell=XBell; - x11.XLookupString=XLookupString; - x11.XNextEvent=XNextEvent; - x11.XAllocSizeHints=XAllocSizeHints; - x11.XSetWMNormalHints=XSetWMNormalHints; - x11.XResizeWindow=XResizeWindow; - x11.XMapWindow=XMapWindow; - x11.XFree=XFree; - x11.XFreePixmap=XFreePixmap; - x11.XCreateBitmapFromData=XCreateBitmapFromData; - x11.XAllocColor=XAllocColor; - x11.XOpenDisplay=XOpenDisplay; - x11.XCreateSimpleWindow=XCreateSimpleWindow; - x11.XCreateGC=XCreateGC; - x11.XSelectInput=XSelectInput; - x11.XStoreName=XStoreName; - x11.XGetSelectionOwner=XGetSelectionOwner; - x11.XConvertSelection=XConvertSelection; - x11.XGetWindowProperty=XGetWindowProperty; - x11.XChangeProperty=XChangeProperty; - x11.XSendEvent=XSendEvent; - x11.XSetSelectionOwner=XSetSelectionOwner; - x11.XSetIconName=XSetIconName; -#else -#if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__) - if((dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL))==NULL) -#else - if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL) -#endif - return(-1); - if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XBell=dlsym(dl,"XBell"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XFree=dlsym(dl,"XFree"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) { - dlclose(dl); - return(-1); - } - if((x11.XSetIconName=dlsym(dl,"XSetIconName"))==NULL) { - dlclose(dl); - return(-1); - } -#endif - - sem_init(&console_mode_changed,0,0); - sem_init(©buf_set,0,0); - sem_init(&pastebuf_request,0,0); - sem_init(&pastebuf_set,0,0); - sem_init(&x11_beep,0,0); - sem_init(&x11_title,0,0); - sem_init(&x11_name,0,0); - sem_init(&font_set,0,0); - sem_init(&x11_loadfont,0,0); - sem_init(&x11_fontloaded,0,0); - - pthread_mutex_init(©buf_mutex, NULL); - pthread_mutex_init(&lines_mutex, NULL); - - if(kbd_init()) { - return(-1); - } - - if(video_init()) { - return(-1); - } - - _beginthread(video_async_event,1<<16,NULL); - _beginthread(mouse_event,1<<16,NULL); - - return(0); -} - -int -video_init() -{ - /* If we are running under X, get a connection to the X server and create - an empty window of size (1, 1). It makes a couple of init functions a - lot easier. */ - if(init_window()) - return(-1); - - /* Initialize mode 3 (text, 80x25, 16 colors) */ - if(init_mode(3)) { - return(-1); - } - sem_wait(&console_mode_changed); - - return(0); -} - -WORD -KbdPeek() -{ - return(K_BUF(K_NEXT)); -} - -WORD -KbdRead() -{ - int kf = K_NEXT; - WORD ret; - - K_NEXT = K_NEXT + 2; - if (K_NEXT == K_BUFENDP) - K_NEXT = K_BUFSTARTP; - - ret=K_BUF(kf); - if(x_pending_mousekeys) { - KbdWrite(CIO_KEY_MOUSE); - x_pending_mousekeys--; - } - return(ret); -} - -int -KbdEmpty(void) -{ - return(K_NEXT == K_FREE); -} - -int x_nextchar = 0; - -int -tty_read(int flag) -{ - int r; - - if ((r = x_nextchar) != 0) { - x_nextchar = 0; - return(r & 0xff); - } - - if (KbdEmpty()) { - if (flag & TTYF_BLOCK) { - while (KbdEmpty()) - tty_pause(); - } else { - return(-1); - } - } - - r = KbdRead(); - if ((r & 0xff) == 0 || (r & 0xff) == 0xff) - x_nextchar = r >> 8; - r &= 0xff; - return(r & 0xff); -} - -int -tty_peek(int flag) -{ - int c; - - if (c == x_nextchar) - return(x_nextchar & 0xff); - - if (KbdEmpty()) { - if (flag & TTYF_POLL) { - sleep_poll(); - if (KbdEmpty()) - return(0); - } else if (flag & TTYF_BLOCK) { - while (KbdEmpty()) - tty_pause(); - } else - return(0); - } - c = KbdPeek(); - return(0xff); -} - -int -tty_kbhit(void) -{ - if(x_nextchar || !KbdEmpty()) - return(1); - return(0); -} - -void x_win_title(const char *title) -{ - SAFECOPY(window_title,title); - sem_post(&x11_title); -} - -void x_win_name(const char *name) -{ - SAFECOPY(window_name,name); - sem_post(&x11_name); -} - -int x_load_font(const char *filename) -{ - SAFECOPY(font_filename, filename); - sem_post(&x11_loadfont); - sem_wait(&x11_fontloaded); - return(x_load_font_ret); -} diff --git a/src/conio/console.h b/src/conio/console.h deleted file mode 100644 index c87b9dbd100548b4ec8f9bb73acb77772eed7d90..0000000000000000000000000000000000000000 --- a/src/conio/console.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id$ */ - -/**************************************************************************** - * @format.tab-size 4 (Plain Text/Source Code File Header) * - * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * - * * - * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * See the GNU Lesser General Public License for more details: lgpl.txt or * - * http://www.fsf.org/copyleft/lesser.html * - * * - * Anonymous FTP access to the most recent released source is available at * - * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * - * * - * Anonymous CVS access to the development source and modification history * - * is available at cvs.synchro.net:/cvsroot/sbbs, example: * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * - * (just hit return, no password is necessary) * - * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * - * * - * For Synchronet coding style and modification guidelines, see * - * http://www.synchro.net/source.html * - * * - * You are encouraged to submit any modifications (preferably in Unix diff * - * format) via e-mail to mods@synchro.net * - * * - * Note: If this box doesn't appear square, then you need to fix your tabs. * - ****************************************************************************/ - - -#ifndef _CONSOLE_H_ -#define _CONSOLE_H_ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/user.h> - -#include <gen_defs.h> -#include <semwrap.h> - -#include "vidmodes.h" - -extern sem_t console_mode_changed; -extern sem_t copybuf_set; -extern sem_t pastebuf_request; -extern sem_t pastebuf_set; -extern sem_t font_set; -extern int new_font; -extern int font_force; -extern int setfont_return; -extern pthread_mutex_t copybuf_mutex; -extern char *copybuf; -extern char *pastebuf; - -extern int CurrMode; - -extern int InitCS; -extern int InitCE; - -extern WORD *vmem; - -extern BYTE CursRow; -extern BYTE CursCol; -extern BYTE CursStart; -extern BYTE CursEnd; - -extern WORD DpyCols; -extern BYTE DpyRows; - -extern int FH,FW; - -extern int x_nextchar; - -extern int console_new_mode; - -extern int x11_window_xpos; -extern int x11_window_ypos; -extern int x11_window_width; -extern int x11_window_height; - -int init_window(); -int video_init(); -int init_mode(int mode); -int tty_read(int flag); -int tty_peek(int flag); -int tty_kbhit(void); -void tty_beep(void); -void x_win_title(const char *title); -int console_init(void); -int x_load_font(const char *filename); - -#define TTYF_BLOCK 0x00000008 -#define TTYF_POLL 0x00000010 -#define NO_NEW_MODE -999 - -#endif diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c index 9c2c318ba56d498f526ff912f3b7f04d11a50e00..e446c1d8344266f1f8eecd6aec831735d6ca41da 100644 --- a/src/conio/sdl_con.c +++ b/src/conio/sdl_con.c @@ -1,5 +1,3 @@ -/* $Id$ */ - #if (defined(__MACH__) && defined(__APPLE__)) #include <Carbon/Carbon.h> #endif @@ -16,6 +14,7 @@ #include "genwrap.h" #include "dirwrap.h" #include "xpbeep.h" +#include "threadwrap.h" #if (defined CIOLIB_IMPORTS) #undef CIOLIB_IMPORTS @@ -28,50 +27,45 @@ #include "keys.h" #include "vidmodes.h" #include "allfonts.h" +#include "bitmap_con.h" #include "SDL.h" #include "SDL_thread.h" #include "sdlfuncs.h" -/********************************************************/ -/* Low Level Stuff */ -/* This should all be called from the same thread! */ -/********************************************************/ +int bitmap_width,bitmap_height; + +/* 256 bytes so I can cheat */ +unsigned char sdl_keybuf[256]; /* Keyboard buffer */ +unsigned char sdl_key=0; /* Index into keybuf for next key in buffer */ +unsigned char sdl_keynext=0; /* Index into keybuf for next free position */ -SDL_Surface *win=NULL; -SDL_mutex *sdl_keylock; -SDL_mutex *sdl_updlock; -SDL_mutex *sdl_vstatlock; -SDL_mutex *sdl_ufunc_lock; -SDL_sem *sdl_key_pending; -SDL_sem *sdl_init_complete; -SDL_sem *sdl_ufunc_ret; -int sdl_ufunc_retval; -int sdl_init_good=0; -int sdl_updated; int sdl_exitcode=0; -SDL_Surface *sdl_font=NULL; -SDL_Surface *sdl_cursor=NULL; +SDL_Surface *win=NULL; SDL_Surface *sdl_icon=NULL; +SDL_Surface *new_rect=NULL; -static int lastcursor_x=0; -static int lastcursor_y=0; -static int sdl_current_font=-99; -static int lastfg=-1; -static int lastbg=-1; -static unsigned int sdl_pending_mousekeys=0; -static SDL_Thread *blinker_thread; +/* *nix copy/paste stuff */ +SDL_sem *sdl_pastebuf_set; +SDL_sem *sdl_pastebuf_copied; +SDL_mutex *sdl_copybuf_mutex; static SDL_Thread *mouse_thread; +char *sdl_copybuf=NULL; +char *sdl_pastebuf=NULL; + +SDL_mutex *sdl_ufunc_lock; +SDL_sem *sdl_ufunc_ret; +int sdl_ufunc_retval; -struct video_stats vstat; int fullscreen=0; -/* 256 bytes so I can cheat */ -unsigned char sdl_keybuf[256]; /* Keyboard buffer */ -unsigned char sdl_key=0; /* Index into keybuf for next key in buffer */ -unsigned char sdl_keynext=0; /* Index into keybuf for next free position */ +SDL_sem *sdl_init_complete; +int sdl_init_good=0; +SDL_mutex *sdl_keylock; +SDL_sem *sdl_key_pending; +static unsigned int sdl_pending_mousekeys=0; struct sdl_keyvals { int keysym @@ -81,13 +75,12 @@ struct sdl_keyvals { ,alt; }; -struct sdl_drawchar { - int x - ,y - ,ch - ,fg - ,bg - ,blink; +struct update_rect { + int x; + int y; + int width; + int height; + unsigned char *data; }; enum { @@ -101,7 +94,6 @@ enum { ,SDL_USEREVENT_INIT ,SDL_USEREVENT_COPY ,SDL_USEREVENT_PASTE - ,SDL_USEREVENT_LOADFONT ,SDL_USEREVENT_QUIT }; @@ -199,12 +191,6 @@ const struct sdl_keyvals sdl_keyval[] = {SDLK_BACKQUOTE, '`', '~', 0, 0x2900}, {0, 0, 0, 0, 0} /** END **/ }; -/* *nix copy/paste stuff */ -SDL_sem *sdl_pastebuf_set; -SDL_sem *sdl_pastebuf_copied; -SDL_mutex *sdl_copybuf_mutex; -char *sdl_copybuf=NULL; -char *sdl_pastebuf=NULL; #if !defined(NO_X) && defined(__unix__) #include "SDL_syswm.h" @@ -231,7 +217,6 @@ struct x11 { struct x11 sdl_x11; #endif -/* Called from all threads */ void sdl_user_func(int func, ...) { unsigned int *i; @@ -246,13 +231,8 @@ void sdl_user_func(int func, ...) va_start(argptr, func); switch(func) { case SDL_USEREVENT_UPDATERECT: - /* Only send event if the last event wasn't already handled */ - sdl.mutexP(sdl_updlock); - if(sdl_updated) { - if(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)==1); - sdl_updated=0; - } - sdl.mutexV(sdl_updlock); + ev.user.data1=va_arg(argptr, struct update_rect *); + while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); break; case SDL_USEREVENT_SETNAME: if((ev.user.data1=strdup(va_arg(argptr, char *)))==NULL) { @@ -319,17 +299,6 @@ int sdl_user_func_ret(int func, ...) ev.user.code=func; va_start(argptr, func); switch(func) { - case SDL_USEREVENT_LOADFONT: - p=va_arg(argptr, char *); - if(p!=NULL) { - if((ev.user.data1=strdup(p))==NULL) { - va_end(argptr); - return(-1); - } - } - while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); - passed=TRUE; - break; case SDL_USEREVENT_QUIT: while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); passed=TRUE; @@ -450,22 +419,21 @@ char *sdl_getcliptext(void) return(ret); } -/* Blinker Thread */ -int sdl_blinker_thread(void *data) +void sdl_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data) { - while(1) { - SLEEP(500); - sdl.mutexP(sdl_vstatlock); - if(vstat.blink) - vstat.blink=FALSE; - else - vstat.blink=TRUE; - sdl.mutexV(sdl_vstatlock); - sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0); + struct update_rect *rect; + + rect=(struct update_rect *)malloc(sizeof(struct update_rect)); + if(sdl_init_good) { + rect->x=xoffset; + rect->y=yoffset; + rect->width=width; + rect->height=height; + rect->data=data; + sdl_user_func(SDL_USEREVENT_UPDATERECT, rect); } } -/* Called from main thread only (Passes Event) */ int sdl_init_mode(int mode) { struct video_params vmode; @@ -473,10 +441,7 @@ int sdl_init_mode(int mode) int i; int oldcols=vstat.cols; - sdl.mutexP(sdl_vstatlock); - - if(load_vmode(&vstat, mode)) - return(-1); + bitmap_init_mode(mode, &bitmap_width, &bitmap_height); /* Deal with 40 col doubling */ if(oldcols != vstat.cols) { @@ -491,49 +456,9 @@ int sdl_init_mode(int mode) sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols*vstat.scaling, vstat.charheight*vstat.rows*vstat.scaling); - /* Initialize video memory with black background, white foreground */ - for (i = 0; i < vstat.cols*vstat.rows; ++i) - vstat.vmem[i] = 0x0700; - vstat.currattr=7; - - cio_textinfo.attribute=7; - cio_textinfo.normattr=7; - cio_textinfo.currmode=mode; - cio_textinfo.screenheight=vstat.rows; - cio_textinfo.screenwidth=vstat.cols; - cio_textinfo.curx=1; - cio_textinfo.cury=1; - cio_textinfo.winleft=1; - cio_textinfo.wintop=1; - cio_textinfo.winright=cio_textinfo.screenwidth; - cio_textinfo.winbottom=cio_textinfo.screenheight; - - vstat.mode=mode; - sdl.mutexV(sdl_vstatlock); - - sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0); - return(0); } -/* Called from main thread only (Passes Event) */ -int sdl_draw_char(unsigned short vch, int xpos, int ypos, int update) -{ - sdl.mutexP(sdl_vstatlock); - vstat.vmem[ypos*vstat.cols+xpos]=vch; - sdl.mutexV(sdl_vstatlock); - - if(update) { -#if 0 /* Currently, an update always updates the whole screen... so don't hold the mutex */ - sdl_user_func(SDL_USEREVENT_UPDATERECT,xpos*vstat.charwidth*vstat.scaling,ypos*vstat.charheight*vstat.scaling,vstat.charwidth*vstat.scaling,vstat.charheight*vstat.scaling); -#else - sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0); -#endif - } - - return(0); -} - /* Called from main thread only (Passes Event) */ int sdl_init(int mode) { @@ -544,15 +469,8 @@ int sdl_init(int mode) if(init_sdl_video()) return(-1); - sdl.mutexP(sdl_vstatlock); - vstat.vmem=NULL; - vstat.scaling=1; - vstat.cols=80; /* Initialize this so sdl_init_mode() is happy */ - sdl.mutexV(sdl_vstatlock); + bitmap_init(sdl_drawrect); - sdl.mutexP(sdl_updlock); - sdl_updated=1; - sdl.mutexV(sdl_updlock); if(mode==CIOLIB_MODE_SDL_FULLSCREEN) fullscreen=1; sdl_init_mode(3); @@ -609,83 +527,6 @@ int sdl_init(int mode) return(-1); } -/********************************************************/ -/* High Level Stuff */ -/********************************************************/ - -/* Called from main thread only (Passes Event) */ -int sdl_puttext(int sx, int sy, int ex, int ey, void *fill) -{ - int x,y; - unsigned char *out; - WORD sch; - struct text_info ti; - - gettextinfo(&ti); - - if( sx < 1 - || sy < 1 - || ex < 1 - || ey < 1 - || sx > ti.screenwidth - || sy > ti.screenheight - || sx > ex - || sy > ey - || ex > ti.screenwidth - || ey > ti.screenheight - || fill==NULL) - return(0); - - out=fill; - sdl.mutexP(sdl_vstatlock); - for(y=sy-1;y<ey;y++) { - for(x=sx-1;x<ex;x++) { - sch=*(out++); - sch |= (*(out++))<<8; - vstat.vmem[y*vstat.cols+x]=sch; - } - } - sdl.mutexV(sdl_vstatlock); - sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0); - return(1); -} - -/* Called from main thread only */ -int sdl_gettext(int sx, int sy, int ex, int ey, void *fill) -{ - int x,y; - unsigned char *out; - WORD sch; - struct text_info ti; - - gettextinfo(&ti); - - if( sx < 1 - || sy < 1 - || ex < 1 - || ey < 1 - || sx > ti.screenwidth - || sy > ti.screenheight - || sx > ex - || sy > ey - || ex > ti.screenwidth - || ey > ti.screenheight - || fill==NULL) - return(0); - - out=fill; - sdl.mutexP(sdl_vstatlock); - for(y=sy-1;y<ey;y++) { - for(x=sx-1;x<ex;x++) { - sch=vstat.vmem[y*vstat.cols+x]; - *(out++)=sch & 0xff; - *(out++)=sch >> 8; - } - } - sdl.mutexV(sdl_vstatlock); - return(1); -} - /* Called from main thread only */ int sdl_kbhit(void) { @@ -697,41 +538,6 @@ int sdl_kbhit(void) return(ret); } -/* Called from main thread only */ -void sdl_gotoxy(int x, int y) -{ - sdl.mutexP(sdl_vstatlock); - if((x-1 != vstat.curs_col) || (y-1 !=vstat.curs_row)) { - vstat.curs_row=y-1; - vstat.curs_col=x-1; - sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0); - } - cio_textinfo.curx=x; - cio_textinfo.cury=y; - sdl.mutexV(sdl_vstatlock); -} - -/* Called from main thread only */ -void sdl_setcursortype(int type) -{ - sdl.mutexP(sdl_vstatlock); - switch(type) { - case _NOCURSOR: - vstat.curs_start=0xff; - vstat.curs_end=0; - break; - case _SOLIDCURSOR: - vstat.curs_start=0; - vstat.curs_end=vstat.charheight-1; - break; - default: - vstat.curs_start = vstat.default_curs_start; - vstat.curs_end = vstat.default_curs_end; - break; - } - sdl.mutexV(sdl_vstatlock); -} - /* Called from main thread only */ int sdl_getch(void) { @@ -790,68 +596,6 @@ int sdl_hidemouse(void) return(0); } -int sdl_loadfont(char *filename) -{ - int retval; - - retval=sdl_user_func_ret(SDL_USEREVENT_LOADFONT,filename); - return(retval); -} - -int sdl_setfont(int font, int force) -{ - int changemode=0; - int newmode=-1; - - if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) - return(-1); - - if(conio_fontdata[font].eight_by_sixteen!=NULL) - newmode=C80; - else if(conio_fontdata[font].eight_by_fourteen!=NULL) - newmode=C80X28; - else if(conio_fontdata[font].eight_by_eight!=NULL) - newmode=C80X50; - - switch(vstat.charheight) { - case 8: - if(conio_fontdata[font].eight_by_eight==NULL) { - if(force) - return(-1); - else - changemode=1; - } - break; - case 14: - if(conio_fontdata[font].eight_by_fourteen==NULL) { - if(force) - return(-1); - else - changemode=1; - } - break; - case 16: - if(conio_fontdata[font].eight_by_sixteen==NULL) { - if(force) - return(-1); - else - changemode=1; - } - break; - } - if(changemode && newmode==-1) - return(-1); - sdl_current_font=font; - if(changemode) - sdl_init_mode(3); - return(sdl_user_func_ret(SDL_USEREVENT_LOADFONT,NULL)); -} - -int sdl_getfont(void) -{ - return(sdl_current_font); -} - int sdl_get_window_info(int *width, int *height, int *xpos, int *ypos) { if(width) @@ -872,9 +616,7 @@ void sdl_add_key(unsigned int keyval) if(keyval==0xa600) { fullscreen=!fullscreen; cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL; - sdl.mutexP(sdl_vstatlock); sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols, vstat.charheight*vstat.rows); - sdl.mutexV(sdl_vstatlock); return; } if(keyval <= 0xffff) { @@ -902,330 +644,22 @@ void sdl_add_key(unsigned int keyval) } } -/* Called from event thread only */ -int sdl_load_font(char *filename) -{ - static char current_filename[MAX_PATH]; - unsigned char *font; - unsigned int fontsize; - int fw; - int fh; - int ch; - int x; - int y; - int charrow; - int charcol; - SDL_Rect r; - FILE *fontfile; - - if(sdl_current_font==-99 || sdl_current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) { - for(x=0; conio_fontdata[x].desc != NULL; x++) { - if(!strcmp(conio_fontdata[x].desc, "Codepage 437 English")) { - sdl_current_font=x; - break; - } - } - if(conio_fontdata[x].desc==NULL) - sdl_current_font=0; - } - if(sdl_current_font==-1) - filename=current_filename; - else if(conio_fontdata[sdl_current_font].desc==NULL) - return(-1); - - sdl.mutexP(sdl_vstatlock); - fh=vstat.charheight; - fw=vstat.charwidth/8+(vstat.charwidth%8?1:0); - - fontsize=fw*fh*256*sizeof(unsigned char); - - if((font=(unsigned char *)malloc(fontsize))==NULL) { - sdl.mutexV(sdl_vstatlock); - return(-1); - } - - if(filename != NULL) { - if(flength(filename)!=fontsize) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - if((fontfile=fopen(filename,"rb"))==NULL) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - if(fread(font, 1, fontsize, fontfile)!=fontsize) { - sdl.mutexV(sdl_vstatlock); - free(font); - fclose(fontfile); - return(-1); - } - fclose(fontfile); - sdl_current_font=-1; - if(filename != current_filename) - SAFECOPY(current_filename,filename); - } - else { - switch(vstat.charwidth) { - case 8: - switch(vstat.charheight) { - case 8: - if(conio_fontdata[sdl_current_font].eight_by_eight==NULL) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - memcpy(font, conio_fontdata[sdl_current_font].eight_by_eight, fontsize); - break; - case 14: - if(conio_fontdata[sdl_current_font].eight_by_fourteen==NULL) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - memcpy(font, conio_fontdata[sdl_current_font].eight_by_fourteen, fontsize); - break; - case 16: - if(conio_fontdata[sdl_current_font].eight_by_sixteen==NULL) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - memcpy(font, conio_fontdata[sdl_current_font].eight_by_sixteen, fontsize); - break; - default: - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - break; - default: - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - } - - if(sdl_font!=NULL) - sdl.FreeSurface(sdl_font); - sdl_font=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*256*vstat.scaling, 8, 0, 0, 0, 0); - if(sdl_font == NULL) { - sdl.mutexV(sdl_vstatlock); - free(font); - return(-1); - } - else { - for(ch=0; ch<256; ch++) { - for(charrow=0; charrow<vstat.charheight; charrow++) { - for(charcol=0; charcol<vstat.charwidth; charcol++) { - if(font[(ch*vstat.charheight+charrow)*fw+(charcol/8)] & (0x80 >> (charcol%8))) { - r.x=charcol*vstat.scaling; - r.y=(ch*vstat.charheight+charrow)*vstat.scaling; - r.w=vstat.scaling; - r.h=vstat.scaling; - sdl.FillRect(sdl_font, &r, 1); - } - } - } - } - } - sdl.mutexV(sdl_vstatlock); - free(font); - lastfg=-1; - lastbg=-1; - return(0); -} - /* Called from events thread only */ -int sdl_setup_colours(SDL_Surface *surf, int xor) +int sdl_setup_colours(SDL_Surface *surf) { int i; int ret=0; - SDL_Color co[16]; + SDL_Color co[sizeof(dac_default)/sizeof(struct dac_colors)]; - sdl.mutexP(sdl_vstatlock); - for(i=0; i<16; i++) { - co[i^xor].r=dac_default[vstat.palette[i]].red; - co[i^xor].g=dac_default[vstat.palette[i]].green; - co[i^xor].b=dac_default[vstat.palette[i]].blue; + for(i=0; i<(sizeof(dac_default)/sizeof(struct dac_colors)); i++) { + co[i].r=dac_default[vstat.palette[i]].red; + co[i].g=dac_default[vstat.palette[i]].green; + co[i].b=dac_default[vstat.palette[i]].blue; } - sdl.mutexV(sdl_vstatlock); - sdl.SetColors(surf, co, 0, 16); + sdl.SetColors(surf, co, 0, sizeof(dac_default)/sizeof(struct dac_colors)); return(ret); } -/* Called from events thread only */ -void sdl_draw_cursor(void) -{ - SDL_Rect src; - SDL_Rect dst; - int x; - int y; - - sdl.mutexP(sdl_vstatlock); - if(vstat.blink && vstat.curs_start<=vstat.curs_end) { - dst.x=0; - dst.y=0; - src.x=vstat.curs_col*vstat.charwidth*vstat.scaling; - src.y=(vstat.curs_row*vstat.charheight+vstat.curs_start)*vstat.scaling; - src.w=dst.w=vstat.charwidth*vstat.scaling; - src.h=dst.h=(vstat.curs_end-vstat.curs_start+1)*vstat.scaling; - sdl_setup_colours(sdl_cursor, 0); - sdl.BlitSurface(win, &src, sdl_cursor, &dst); - sdl_setup_colours(sdl_cursor, vstat.currattr&0x07); - sdl.BlitSurface(sdl_cursor, &dst, win, &src); - lastcursor_x=vstat.curs_col; - lastcursor_y=vstat.curs_row; - } - sdl.mutexV(sdl_vstatlock); -} - -/* Called from event thread */ -/* ONLY Called from sdl_full_screen_redraw() which holds the mutex... */ -int sdl_draw_one_char(unsigned short sch, unsigned int x, unsigned int y, struct video_stats *vs) -{ - SDL_Color co; - SDL_Rect src; - SDL_Rect dst; - unsigned char ch; - - ch=(sch >> 8) & 0x0f; - if(lastfg!=ch) { - co.r=dac_default[vs->palette[ch]].red; - co.g=dac_default[vs->palette[ch]].green; - co.b=dac_default[vs->palette[ch]].blue; - sdl.SetColors(sdl_font, &co, 1, 1); - lastfg=ch; - } - ch=(sch >> 12) & 0x07; - if(lastbg!=ch) { - co.r=dac_default[vs->palette[ch]].red; - co.g=dac_default[vs->palette[ch]].green; - co.b=dac_default[vs->palette[ch]].blue; - sdl.SetColors(sdl_font, &co, 0, 1); - lastbg=ch; - } - dst.x=x*vs->charwidth*vs->scaling; - dst.y=y*vs->charheight*vs->scaling; - dst.w=vs->charwidth*vs->scaling; - dst.h=vs->charheight*vs->scaling; - src.x=0; - src.w=vs->charwidth*vs->scaling; - src.h=vs->charheight*vs->scaling; - src.y=vs->charheight*vs->scaling; - ch=sch & 0xff; - if((sch >>15) && !(vs->blink)) - src.y *= ' '; - else - src.y *= ch; - if(sdl_font != NULL) - sdl.BlitSurface(sdl_font, &src, win, &dst); - return(0); -} - - -/* Called from event thread only, */ -int sdl_full_screen_redraw(int force) -{ - static int last_blink; - int x; - int y; - unsigned int pos; - unsigned short *p; - unsigned short *newvmem; - static unsigned short *vmemcopies[2]={ NULL, NULL }; - static SDL_Rect *rects=NULL; - static int this_new=0; - static unsigned short *last_vmem=NULL; - int rcount=0; - static struct video_stats vs; - int redraw_cursor=0; - int lastlineupdated=0; - int lastcharupdated=0; - - sdl.mutexP(sdl_vstatlock); - if(vs.cols!=vstat.cols || vs.rows != vstat.rows || vmemcopies[0]==NULL || vmemcopies[1]==NULL || rects==NULL) { - FREE_AND_NULL(vmemcopies[0]); - if((vmemcopies[0]=(unsigned short *)malloc(vstat.cols*vstat.rows*sizeof(unsigned short)))==NULL) { - sdl.mutexV(sdl_vstatlock); - return(-1); - } - FREE_AND_NULL(vmemcopies[1]); - if((vmemcopies[1]=(unsigned short *)malloc(vstat.cols*vstat.rows*sizeof(unsigned short)))==NULL) { - sdl.mutexV(sdl_vstatlock); - return(-1); - } - FREE_AND_NULL(rects); - if((rects=(SDL_Rect *)malloc(sizeof(SDL_Rect)*vstat.cols*vstat.rows))==NULL) { - sdl.mutexV(sdl_vstatlock); - return(-1); - } - } - this_new = (this_new+1) % 2; - newvmem=vmemcopies[this_new]; - memcpy(&vs, &vstat, sizeof(vs)); - memcpy(newvmem, vs.vmem, vs.cols*vs.rows*sizeof(unsigned short)); - sdl.mutexV(sdl_vstatlock); - sdl.mutexP(sdl_updlock); - sdl_updated=1; - sdl.mutexV(sdl_updlock); - /* Redraw all chars */ - pos=0; - if(last_vmem==NULL) - force=1; - if(last_blink != vs.blink - || lastcursor_x!=vs.curs_col - || lastcursor_y!=vs.curs_row) - redraw_cursor=1; - for(y=0;y<vs.rows;y++) { - for(x=0;x<vs.cols;x++) { - if(force - || (last_vmem[pos] != newvmem[pos]) - || (last_blink != vs.blink && newvmem[pos]>>15) - || (redraw_cursor && ((lastcursor_x==x && lastcursor_y==y) || (vs.curs_col==x && vs.curs_row==y))) - ) { - sdl_draw_one_char(newvmem[pos],x,y,&vs); - if(lastcharupdated) { - rects[rcount-1].w+=vs.charwidth*vs.scaling; - lastcharupdated++; - } - else { - rects[rcount].x=x*vs.charwidth*vs.scaling; - rects[rcount].y=y*vs.charheight*vs.scaling; - rects[rcount].w=vs.charwidth*vs.scaling; - rects[rcount++].h=vs.charheight*vs.scaling; - lastcharupdated++; - } - if(!redraw_cursor && x==vs.curs_col && y==vs.curs_row) - redraw_cursor=1; - } - else - lastcharupdated=0; - pos++; - } - if(lastcharupdated==vs.cols) { - if(lastlineupdated) { - rcount--; - rects[rcount-1].h+=vs.charheight*vs.scaling; - } - else - lastlineupdated=1; - } - else - lastlineupdated=0; - lastcharupdated=0; - } - last_blink=vs.blink; - last_vmem=newvmem; - - if(redraw_cursor) - sdl_draw_cursor(); - if(rcount) - sdl.UpdateRects(win,rcount,rects); - return(0); -} - unsigned int cp437_convert(unsigned int unicode) { if(unicode <= 0x80) @@ -1608,28 +1042,20 @@ int sdl_video_event_thread(void *data) case SDL_MOUSEMOTION: if(!ciolib_mouse_initialized) break; - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_MOUSE_MOVE,ev.motion.x/(vstat.charwidth*vstat.scaling)+1,ev.motion.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; case SDL_MOUSEBUTTONDOWN: if(!ciolib_mouse_initialized) break; switch(ev.button.button) { case SDL_BUTTON_LEFT: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; case SDL_BUTTON_MIDDLE: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; case SDL_BUTTON_RIGHT: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; } break; @@ -1638,19 +1064,13 @@ int sdl_video_event_thread(void *data) break; switch(ev.button.button) { case SDL_BUTTON_LEFT: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; case SDL_BUTTON_MIDDLE: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; case SDL_BUTTON_RIGHT: - sdl.mutexP(sdl_vstatlock); ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1); - sdl.mutexV(sdl_vstatlock); break; } break; @@ -1659,7 +1079,7 @@ int sdl_video_event_thread(void *data) return(sdl_exitcode); case SDL_VIDEORESIZE: if(ev.resize.w > 0 && ev.resize.h > 0) { - sdl.mutexP(sdl_vstatlock); + pthread_mutex_lock(&vstatlock); vstat.scaling=(int)(ev.resize.w/(vstat.charwidth*vstat.cols)); if(vstat.scaling < 1) vstat.scaling=1; @@ -1686,25 +1106,27 @@ int sdl_video_event_thread(void *data) sdl_using_quartz=TRUE; } #endif - - if(sdl_cursor!=NULL) - sdl.FreeSurface(sdl_cursor); - sdl_cursor=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*vstat.scaling, 8, 0, 0, 0, 0); - /* Update font. */ - sdl_load_font(NULL); - sdl_setup_colours(win,0); - sdl_full_screen_redraw(TRUE); + if(new_rect) + sdl.FreeSurface(new_rect); + new_rect=sdl.CreateRGBSurface(SDL_SWSURFACE + , vstat.charwidth*vstat.cols*vstat.scaling + , vstat.charheight*vstat.rows*vstat.scaling + , 8, 0, 0, 0, 0); + pthread_mutex_unlock(&vstatlock); + sdl_setup_colours(win); + sdl_setup_colours(new_rect); + send_rectangle(0,0,bitmap_width,bitmap_height,TRUE); } else if(sdl_init_good) { + pthread_mutex_unlock(&vstatlock); ev.type=SDL_QUIT; sdl_exitcode=1; sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff); } - sdl.mutexV(sdl_vstatlock); } break; case SDL_VIDEOEXPOSE: - sdl_full_screen_redraw(TRUE); + send_rectangle(0,0,bitmap_width,bitmap_height,TRUE); break; case SDL_USEREVENT: { /* Tell SDL to do various stuff... */ @@ -1713,15 +1135,36 @@ int sdl_video_event_thread(void *data) sdl_ufunc_retval=0; sdl.SemPost(sdl_ufunc_ret); return(0); - case SDL_USEREVENT_LOADFONT: - sdl_ufunc_retval=sdl_load_font((char *)ev.user.data1); - FREE_AND_NULL(ev.user.data1); - sdl.SemPost(sdl_ufunc_ret); - sdl_full_screen_redraw(TRUE); - break; case SDL_USEREVENT_UPDATERECT: - sdl_full_screen_redraw(FALSE); - break; + { + struct update_rect *rect=(struct update_rect *)ev.user.data1; + SDL_Rect r; + SDL_Rect dst; + int x,y; + + for(y=0; y<rect->height; y++) { + for(x=0; x<rect->width; x++) { + r.x=x*vstat.scaling; + r.y=y*vstat.scaling; + r.w=vstat.scaling; + r.h=vstat.scaling; + sdl.FillRect(new_rect, &r, rect->data[y*rect->width+x]); + } + } + r.x=0; + r.y=0; + r.w=rect->width*vstat.scaling; + r.h=rect->height*vstat.scaling; + dst.x=rect->x*vstat.scaling; + dst.y=rect->y*vstat.scaling; + dst.w=rect->width*vstat.scaling; + dst.h=rect->height*vstat.scaling; + sdl.BlitSurface(new_rect, &r, win, &dst); + sdl.UpdateRects(win,1,&dst); + free(rect->data); + free(rect); + break; + } case SDL_USEREVENT_SETNAME: sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1); free(ev.user.data1); @@ -1747,7 +1190,7 @@ int sdl_video_event_thread(void *data) free(ev.user.data1); break; case SDL_USEREVENT_SETVIDMODE: - sdl.mutexP(sdl_vstatlock); + pthread_mutex_lock(&vstatlock); if(fullscreen) win=sdl.SetVideoMode( vstat.charwidth*vstat.cols*vstat.scaling @@ -1773,22 +1216,25 @@ int sdl_video_event_thread(void *data) vstat.scaling=(int)(win->w/(vstat.charwidth*vstat.cols)); if(vstat.scaling < 1) vstat.scaling=1; - sdl_setup_colours(win,0); - if(sdl_cursor!=NULL) - sdl.FreeSurface(sdl_cursor); - sdl_cursor=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*vstat.scaling, 8, 0, 0, 0, 0); - /* Update font. */ - sdl_load_font(NULL); - sdl_full_screen_redraw(TRUE); + if(new_rect) + sdl.FreeSurface(new_rect); + new_rect=sdl.CreateRGBSurface(SDL_SWSURFACE + , vstat.charwidth*vstat.cols*vstat.scaling + , vstat.charheight*vstat.rows*vstat.scaling + , 8, 0, 0, 0, 0); + pthread_mutex_unlock(&vstatlock); + sdl_setup_colours(win); + sdl_setup_colours(new_rect); + send_rectangle(0,0,bitmap_width,bitmap_height,TRUE); } else if(sdl_init_good) { + pthread_mutex_unlock(&vstatlock); ev.type=SDL_QUIT; sdl_exitcode=1; sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff); } free(ev.user.data1); free(ev.user.data2); - sdl.mutexV(sdl_vstatlock); break; case SDL_USEREVENT_HIDEMOUSE: sdl.ShowCursor(SDL_DISABLE); @@ -1802,7 +1248,6 @@ int sdl_video_event_thread(void *data) if(win != NULL) { sdl.EnableUNICODE(1); sdl.EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - blinker_thread=sdl.CreateThread(sdl_blinker_thread, NULL); mouse_thread=sdl.CreateThread(sdl_mouse_thread, NULL); sdl_init_good=1; } @@ -2005,9 +1450,7 @@ int sdl_initciolib(int mode) sdl_key_pending=sdl.SDL_CreateSemaphore(0); sdl_init_complete=sdl.SDL_CreateSemaphore(0); sdl_ufunc_ret=sdl.SDL_CreateSemaphore(0); - sdl_updlock=sdl.SDL_CreateMutex(); sdl_keylock=sdl.SDL_CreateMutex(); - sdl_vstatlock=sdl.SDL_CreateMutex(); sdl_ufunc_lock=sdl.SDL_CreateMutex(); #if !defined(NO_X) && defined(__unix__) sdl_pastebuf_set=sdl.SDL_CreateSemaphore(0); diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c index 368d02f82b4e0c1060905b8326de77b2e2f072dd..b10bed931bb36cf8d0a79fff0af2385bdb2fe697 100644 --- a/src/conio/x_cio.c +++ b/src/conio/x_cio.c @@ -35,6 +35,11 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#ifndef STATIC_LINK +#include <dlfcn.h> +#endif +#include <sys/types.h> +#include <sys/socket.h> #include <threadwrap.h> @@ -47,145 +52,75 @@ #include "ciolib.h" #include "x_cio.h" -#include "console.h" -WORD x_curr_attr=0x0700; - -int x_puttext(int sx, int sy, int ex, int ey, void *fill) -{ - int x,y; - unsigned char *out; - WORD sch; - struct text_info ti; - - gettextinfo(&ti); - - if( sx < 1 - || sy < 1 - || ex < 1 - || ey < 1 - || sx > ti.screenwidth - || sy > ti.screenheight - || sx > ex - || sy > ey - || ex > ti.screenwidth - || ey > ti.screenheight - || fill==NULL) - return(0); - - out=fill; - for(y=sy-1;y<ey;y++) { - for(x=sx-1;x<ex;x++) { - sch=*(out++); - sch |= (*(out++))<<8; - vmem[y*DpyCols+x]=sch; - } - } - return(1); -} - -int x_gettext(int sx, int sy, int ex, int ey, void *fill) -{ - int x,y; - unsigned char *out; - WORD sch; - struct text_info ti; - - gettextinfo(&ti); - - if( sx < 1 - || sy < 1 - || ex < 1 - || ey < 1 - || sx > ti.screenwidth - || sy > ti.screenheight - || sx > ex - || sy > ey - || ex > ti.screenwidth - || ey > ti.screenheight - || fill==NULL) - return(0); - - out=fill; - for(y=sy-1;y<ey;y++) { - for(x=sx-1;x<ex;x++) { - sch=vmem[y*DpyCols+x]; - *(out++)=sch & 0xff; - *(out++)=sch >> 8; - } - } - return(1); -} +#include "x_events.h" int x_kbhit(void) { - return(tty_kbhit()); -} + fd_set rfd; + struct timeval tv; -void x_gotoxy(int x, int y) -{ - CursRow=cio_textinfo.wintop+y-2; - CursCol=cio_textinfo.winleft+x-2; - cio_textinfo.curx=x; - cio_textinfo.cury=y; -} - -void x_setcursortype(int type) -{ - switch(type) { - case _NOCURSOR: - CursStart=0xff; - CursEnd=0; - break; - case _SOLIDCURSOR: - CursStart=0; - CursEnd=FH-1; - break; - default: - CursStart = InitCS; - CursEnd = InitCE; - break; - } + memset(&tv, 0, sizeof(tv)); + FD_ZERO(&rfd); + FD_SET(key_pipe[0], &rfd); + return(select(key_pipe[0]+1, &rfd, NULL, NULL, &tv)==1); } int x_getch(void) { - return(tty_read(TTYF_BLOCK)); + unsigned char ch; + + while(read(key_pipe[0], &ch, 1)!=1); + return(ch); } int x_beep(void) { - tty_beep(); + struct x11_local_event ev; + + ev.type=X11_LOCAL_BEEP; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); return(0); } void x_textmode(int mode) { - console_new_mode=mode; - sem_wait(&console_mode_changed); + struct x11_local_event ev; + + ev.type=X11_LOCAL_SETMODE; + ev.data.mode = mode; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); + sem_wait(&mode_set); } void x_setname(const char *name) { - x_win_name(name); + struct x11_local_event ev; + + ev.type=X11_LOCAL_SETNAME; + SAFECOPY(ev.data.name, name); + while(write(local_pipe[1], &ev, sizeof(ev))==-1); } void x_settitle(const char *title) { - x_win_title(title); + struct x11_local_event ev; + + ev.type=X11_LOCAL_SETTITLE; + SAFECOPY(ev.data.title, title); + while(write(local_pipe[1], &ev, sizeof(ev))==-1); } void x_copytext(const char *text, size_t buflen) { + struct x11_local_event ev; + pthread_mutex_lock(©buf_mutex); - if(copybuf!=NULL) { - free(copybuf); - copybuf=NULL; - } + FREE_AND_NULL(copybuf); - copybuf=(char *)malloc(buflen+1); - if(copybuf!=NULL) { - strcpy(copybuf, text); - sem_post(©buf_set); + copybuf=strdup(text); + if(copybuf) { + ev.type=X11_LOCAL_COPY; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); } pthread_mutex_unlock(©buf_mutex); return; @@ -194,38 +129,17 @@ void x_copytext(const char *text, size_t buflen) char *x_getcliptext(void) { char *ret=NULL; + struct x11_local_event ev; - sem_post(&pastebuf_request); + ev.type=X11_LOCAL_PASTE; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); sem_wait(&pastebuf_set); - if(pastebuf!=NULL) { - ret=(char *)malloc(strlen(pastebuf)+1); - if(ret!=NULL) - strcpy(ret,pastebuf); - } - sem_post(&pastebuf_request); + if(pastebuf!=NULL) + ret=strdup(pastebuf); + sem_post(&pastebuf_used); return(ret); } -int x_setfont(int font, int force) -{ - if(font==getfont()) - return(0); - font_force=force; - new_font=font; - sem_wait(&font_set); - return(setfont_return); -} - -int x_getfont(void) -{ - return(new_font); -} - -int x_loadfont(char *filename) -{ - return(x_load_font(filename)); -} - int x_get_window_info(int *width, int *height, int *xpos, int *ypos) { if(width) @@ -239,3 +153,279 @@ int x_get_window_info(int *width, int *height, int *xpos, int *ypos) return(0); } + +int x_init(void) +{ + int fd; + int i; + void *dl; + + /* Ensure we haven't already initialized */ + if(initialized) + return(0); + + /* Set up the pipe for local events */ + if(pipe(local_pipe)) + return(-1); + + /* And the keyboard pipe */ + if(pipe(key_pipe)) + return(-1); + + /* Load X11 functions */ +#ifdef STATIC_LINK + x11.XChangeGC=XChangeGC; + x11.XCopyPlane=XCopyPlane; + x11.XFillRectangle=XFillRectangle; + x11.XDrawPoint=XDrawPoint; + x11.XFlush=XFlush; + x11.XSync=XSync; + x11.XBell=XBell; + x11.XLookupString=XLookupString; + x11.XNextEvent=XNextEvent; + x11.XAllocSizeHints=XAllocSizeHints; + x11.XSetWMNormalHints=XSetWMNormalHints; + x11.XResizeWindow=XResizeWindow; + x11.XMapWindow=XMapWindow; + x11.XFree=XFree; + x11.XFreePixmap=XFreePixmap; + x11.XCreatePixmap=XCreatePixmap; + x11.XCopyArea=XCopyArea; + x11.XCreateBitmapFromData=XCreateBitmapFromData; + x11.XAllocColor=XAllocColor; + x11.XOpenDisplay=XOpenDisplay; + x11.XCreateSimpleWindow=XCreateSimpleWindow; + x11.XCreateGC=XCreateGC; + x11.XSelectInput=XSelectInput; + x11.XStoreName=XStoreName; + x11.XGetSelectionOwner=XGetSelectionOwner; + x11.XConvertSelection=XConvertSelection; + x11.XGetWindowProperty=XGetWindowProperty; + x11.XChangeProperty=XChangeProperty; + x11.XSendEvent=XSendEvent; + x11.XPutImage=XPutImage; +#ifndef XPutPixel + x11.XPutPixel=XPutPixel; +#endif +#ifndef XDestroyImage + x11.XDestroyImage=XDestroyImage; +#endif + x11.XCreateImage=XCreateImage; + x11.XSetSelectionOwner=XSetSelectionOwner; + x11.XSetIconName=XSetIconName; + x11.XSynchronize=XSynchronize; + x11.XGetWindowAttributes=XGetWindowAttributes; +#else +#if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__) + if((dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL))==NULL) +#else + if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL) +#endif + return(-1); + if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XDrawPoint=dlsym(dl,"XDrawPoint"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSync=dlsym(dl,"XSync"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XBell=dlsym(dl,"XBell"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XFree=dlsym(dl,"XFree"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCreatePixmap=dlsym(dl,"XCreatePixmap"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCopyArea=dlsym(dl,"XCopyArea"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XPutImage=dlsym(dl,"XPutImage"))==NULL) { + dlclose(dl); + return(-1); + } +#ifndef XDestroyImage + if((x11.XDestroyImage=dlsym(dl,"XDestroyImage"))==NULL) { + dlclose(dl); + return(-1); + } +#endif +#ifndef XPutPixel + if((x11.XPutPixel=dlsym(dl,"XPutPixel"))==NULL) { + dlclose(dl); + return(-1); + } +#endif + if((x11.XCreateImage=dlsym(dl,"XCreateImage"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSetIconName=dlsym(dl,"XSetIconName"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XSynchronize=dlsym(dl,"XSynchronize"))==NULL) { + dlclose(dl); + return(-1); + } + if((x11.XGetWindowAttributes=dlsym(dl,"XGetWindowAttributes"))==NULL) { + dlclose(dl); + return(-1); + } +#endif + + if(sem_init(&pastebuf_set, 0, 0)) + return(-1); + if(sem_init(&pastebuf_used, 0, 0)) { + sem_destroy(&pastebuf_set); + return(-1); + } + if(sem_init(&init_complete, 0, 0)) { + sem_destroy(&pastebuf_set); + sem_destroy(&pastebuf_used); + return(-1); + } + if(sem_init(&mode_set, 0, 0)) { + sem_destroy(&pastebuf_set); + sem_destroy(&pastebuf_used); + sem_destroy(&init_complete); + return(-1); + } + + if(pthread_mutex_init(©buf_mutex, 0)) { + sem_destroy(&pastebuf_set); + sem_destroy(&pastebuf_used); + sem_destroy(&init_complete); + sem_destroy(&mode_set); + return(-1); + } + + _beginthread(x11_event_thread,1<<16,NULL); + sem_wait(&init_complete); + if(!initialized) { + sem_destroy(&pastebuf_set); + sem_destroy(&pastebuf_used); + sem_destroy(&init_complete); + sem_destroy(&mode_set); + pthread_mutex_destroy(©buf_mutex); + return(-1); + } + return(0); +} + +void x11_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data) +{ + struct x11_local_event ev; + + ev.type=X11_LOCAL_DRAWRECT; + if(initialized) { + ev.data.rect.x=xoffset; + ev.data.rect.y=yoffset; + ev.data.rect.width=width; + ev.data.rect.height=height; + ev.data.rect.data=data; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); + } +} diff --git a/src/conio/x_cio.h b/src/conio/x_cio.h index 8d623455e9bb78d000a7b24e77e3c8e8d004b3ef..f46602ab9a62eec680a75365e86943051916f020 100644 --- a/src/conio/x_cio.h +++ b/src/conio/x_cio.h @@ -40,18 +40,25 @@ #endif #include "ciolib.h" -#include "console.h" +#include "x_events.h" #ifdef __cplusplus extern "C" { #endif int x_puttext(int sx, int sy, int ex, int ey, void *fill); int x_gettext(int sx, int sy, int ex, int ey, void *fill); +void x_textattr(int attr); int x_kbhit(void); +void x_delay(long msec); +int x_wherey(void); +int x_wherex(void); +int x_putch(int ch); void x_gotoxy(int x, int y); void x_initciolib(long inmode); +void x_gettextinfo(struct text_info *info); void x_setcursortype(int type); int x_getch(void); +int x_getche(void); int x_beep(void); void x_textmode(int mode); void x_setname(const char *name); @@ -62,6 +69,7 @@ int x_setfont(int font, int force); int x_getfont(void); int x_loadfont(char *filename); int x_get_window_info(int *width, int *height, int *xpos, int *ypos); +void x11_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data); #ifdef __cplusplus } #endif diff --git a/src/conio/x_events.c b/src/conio/x_events.c new file mode 100644 index 0000000000000000000000000000000000000000..54803a9df94c698a27ce2c1326d385b42f0e7163 --- /dev/null +++ b/src/conio/x_events.c @@ -0,0 +1,870 @@ +/* + * This file contains ONLY the functions that are called from the + * event thread. + */ + +#include <unistd.h> + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> + +#include <threadwrap.h> +#include <genwrap.h> +#include <dirwrap.h> + +#include "vidmodes.h" +#include "allfonts.h" + +#include "keys.h" +#include "mouse.h" +#include "bitmap_con.h" +#include "link_list.h" +#include "x_events.h" +#include "x_cio.h" + +/* + * Exported variables + */ + +int local_pipe[2]; /* Used for passing local events */ +int key_pipe[2]; /* Used for passing keyboard events */ + +struct x11 x11; + +char *copybuf; +pthread_mutex_t copybuf_mutex; +char *pastebuf; +sem_t pastebuf_set; +sem_t pastebuf_used; +sem_t init_complete; +sem_t mode_set; +int x11_window_xpos; +int x11_window_ypos; +int x11_window_width; +int x11_window_height; +int initialized=0; +/* + * Local variables + */ + +/* Sets the atom to be used for copy/paste operations */ +#define CONSOLE_CLIPBOARD XA_PRIMARY + +static Display *dpy=NULL; +static Window win; +static Visual visual; +static unsigned int depth=0; +static int xfd; +static unsigned long black; +static unsigned long white; +static int bitmap_width; +static int bitmap_height; + +/* Array of Graphics Contexts */ +static GC gca[sizeof(dac_default)/sizeof(struct dac_colors)]; + +/* Array of pixel values to match all possible colours */ +static unsigned long pixel[sizeof(dac_default)/sizeof(struct dac_colors)]; + +static WORD Ascii2Scan[] = { + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028, + 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035, + 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135, + 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122, + 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118, + 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111, + 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c, + 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022, + 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018, + 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011, + 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff, +}; + +static struct { + WORD base; + WORD shift; + WORD ctrl; + WORD alt; +} ScanCodes[] = { + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */ + { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */ + { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */ + { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */ + { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */ + { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */ + { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */ + { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */ + { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */ + { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */ + { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */ + { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */ + { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */ + { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */ + { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */ + { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */ + { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */ + { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */ + { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */ + { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */ + { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */ + { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */ + { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */ + { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */ + { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */ + { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */ + { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */ + { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */ + { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */ + { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */ + { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */ + { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */ + { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */ + { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */ + { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */ + { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */ + { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */ + { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */ + { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */ + { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */ + { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */ + { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */ + { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */ + { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */ + { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */ + { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */ + { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */ + { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */ + { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */ + { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */ + { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */ + { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */ + { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */ + { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */ + { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */ + { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */ + { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */ + { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */ + { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */ + { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */ + { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */ + { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */ + { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */ + { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */ + { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */ + { 0x4800, 0x4838, 0x8d00, 0x9800 }, /* key 72 - cursor up */ + { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */ + { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */ + { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */ + { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */ + { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */ + { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */ + { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */ + { 0x5000, 0x5032, 0x9100, 0xa000 }, /* key 80 - cursor down */ + { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */ + { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */ + { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */ + { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */ + { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */ + { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */ +}; + +/* Get a connection to the X server and create the window. */ +static int init_window() +{ + XGCValues gcv; + XColor color; + int i; + XWindowAttributes attr; + + dpy = x11.XOpenDisplay(NULL); + if (dpy == NULL) { + return(-1); + } + xfd = ConnectionNumber(dpy); + + /* Allocate black and white */ + black=BlackPixel(dpy, DefaultScreen(dpy)); + white=WhitePixel(dpy, DefaultScreen(dpy)); + + /* Create window, but defer setting a size and GC. */ + win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, + 1, 1, 2, black, black); + + gcv.function = GXcopy; + gcv.foreground = white; + gcv.background = black; + gcv.graphics_exposures = False; + + /* Get the pixel and GC values */ + for(i=0; i<sizeof(dac_default)/sizeof(struct dac_colors); i++) { + color.red=dac_default[i].red << 8; + color.green=dac_default[i].green << 8; + color.blue=dac_default[i].blue << 8; + if(x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) + pixel[i]=color.pixel; + gcv.foreground=color.pixel; + gca[i]=x11.XCreateGC(dpy, win, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv); + } + + x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask | + ExposureMask | ButtonPressMask + | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask); +// x11.XFlush(dpy); + x11.XGetWindowAttributes(dpy,win,&attr); + memcpy(&visual,attr.visual,sizeof(visual)); + + x11.XStoreName(dpy, win, "SyncConsole"); + depth = DefaultDepth(dpy, DefaultScreen(dpy)); + + return(0); +} + +/* Resize the window. This function is called after a mode change. */ +static void resize_window() +{ + XSizeHints *sh; + + sh = x11.XAllocSizeHints(); + if (sh == NULL) { + fprintf(stderr, "Could not get XSizeHints structure"); + exit(1); + } + + sh->base_width = bitmap_width*vstat.scaling; + sh->base_height = bitmap_height*vstat.scaling; + + sh->min_width = bitmap_width; + sh->min_height = bitmap_height; + sh->flags = USSize | PMinSize | PSize; + + x11.XSetWMNormalHints(dpy, win, sh); + x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height); + x11.XMapWindow(dpy, win); + + x11.XFree(sh); + + send_rectangle(0,0,bitmap_width,bitmap_height,TRUE); + + return; +} + +static int init_mode(int mode) +{ + int i; + + bitmap_init_mode(mode, &bitmap_width, &bitmap_height); + + /* Resize window if necessary. */ + resize_window(); + + sem_post(&mode_set); + return(0); +} + +static int video_init() +{ + /* If we are running under X, get a connection to the X server and create + an empty window of size (1, 1). It makes a couple of init functions a + lot easier. */ + if(init_window()) + return(-1); + + vstat.scaling=1; + bitmap_init(x11_drawrect); + + /* Initialize mode 3 (text, 80x25, 16 colors) */ + if(init_mode(3)) { + return(-1); + } + + sem_wait(&mode_set); + + return(0); +} + +static void local_draw_rect(struct update_rect *rect) +{ + int x,y,xscale,yscale; + int rectw, recth, rectc,x2,y2; + XImage *xim; + +#if 0 + /* Draw solid colour rectangles... */ + for(y=0; y<rect->height; y++) { + for(x=0; x<rect->width; x++) { + rectc=rect->data[y*rect->width+x]; + + /* Already displayed? */ + if(rectc == 255) + continue; + + rectw=1; + recth=1; + + /* Grow as wide as we can */ + while(x+rectw < rect->width && rect->data[y*rect->width+x+rectw]==rectc) + rectw++; + + /* Now grow as tall as we can */ + while(y+recth < rect->height && memcmp(rect->data+(y*rect->width+x), rect->data+((y+recth)*rect->width+x), rectw)==0) + recth++; + + /* Mark pixels as drawn */ + for(y2=0; y2<recth; y2++) + memset(rect->data+((y+y2)*rect->width+x),255,rectw); + + /* Draw it */ + x11.XFillRectangle(dpy, win, gca[rectc], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling, rectw*vstat.scaling, recth*vstat.scaling); + } + } +#endif + +#if 1 /* Other Methods */ +#if 1 /* XImage */ + xim=x11.XCreateImage(dpy,&visual,depth,ZPixmap,0,NULL,rect->width,rect->height,32,0); + xim->data=(char *)malloc(xim->bytes_per_line*rect->height); + for(y=0;y<rect->height;y++) { + for(x=0; x<rect->width; x++) { + for(yscale=0; yscale<vstat.scaling; yscale++) { + for(xscale=0; xscale<vstat.scaling; xscale++) { +#ifdef XPutPixel + XPutPixel(xim,x*vstat.scaling+xscale,y*vstat.scaling+yscale,pixel[rect->data[y*rect->width+x]]); +#else + x11.XPutPixel(xim,x*vstat.scaling+xscale,y*vstat.scaling+yscale,pixel[rect->data[y*rect->width+x]]); +#endif + } + } + } + } + + x11.XPutImage(dpy,win,gca[0],xim,0,0,(rect->x),(rect->y),rect->width,rect->height); +#ifdef XDestroyImage + XDestroyImage(xim); +#else + x11.XDestroyImage(xim); +#endif + +#else /* XFillRectangle */ + for(y=0;y<rect->height;y++) { + for(x=0; x<rect->width; x++) { + x11.XFillRectangle(dpy, win, gca[rect->data[y*rect->width+x]], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling, vstat.scaling, vstat.scaling); + } + } +#endif +#endif + x11.XFlush(dpy); + free(rect->data); +} + +static int x11_event(XEvent *ev) +{ + switch (ev->type) { + /* Graphics related events */ + case ConfigureNotify: + { + int newFSH=1; + int newFSW=1; + int r; + + x11_window_xpos=ev->xconfigure.x; + x11_window_ypos=ev->xconfigure.y; + x11_window_width=ev->xconfigure.width; + x11_window_height=ev->xconfigure.height; + if((ev->xconfigure.width == vstat.charwidth * vstat.cols * vstat.scaling) + && (ev->xconfigure.height == vstat.charheight * vstat.rows * vstat.scaling)) + break; + + newFSH=ev->xconfigure.width/bitmap_width; + newFSW=ev->xconfigure.height/bitmap_height; + if(newFSW<1) + newFSW=1; + if(newFSH<1) + newFSH=1; + if(newFSH<newFSW) + vstat.scaling=newFSH; + else + vstat.scaling=newFSW; + if(vstat.scaling > 16) + vstat.scaling=16; + resize_window(); + } + break; + case NoExpose: + break; + case GraphicsExpose: + send_rectangle(ev->xgraphicsexpose.x/vstat.scaling,ev->xgraphicsexpose.y/vstat.scaling + ,ev->xgraphicsexpose.width/vstat.scaling,ev->xgraphicsexpose.height/vstat.scaling,TRUE); + break; + case Expose: + send_rectangle(ev->xexpose.x/vstat.scaling,ev->xexpose.y/vstat.scaling,ev->xexpose.width/vstat.scaling,ev->xexpose.height/vstat.scaling,TRUE); + break; + + /* Copy/Paste events */ + case SelectionClear: + { + XSelectionClearEvent *req; + + req=&(ev->xselectionclear); + pthread_mutex_lock(©buf_mutex); + if(req->selection==CONSOLE_CLIPBOARD) + FREE_AND_NULL(copybuf); + pthread_mutex_unlock(©buf_mutex); + } + break; + case SelectionNotify: + { + int format; + unsigned long len, bytes_left, dummy; + Atom type; + + if(ev->xselection.selection != CONSOLE_CLIPBOARD) + break; + if(ev->xselection.requestor!=win) + break; + x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf)); + if(bytes_left > 0 && format==8) + x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf); + else + pastebuf=NULL; + + /* Set paste buffer */ + sem_post(&pastebuf_set); + sem_wait(&pastebuf_used); + x11.XFree(pastebuf); + pastebuf=NULL; + } + break; + case SelectionRequest: + { + XSelectionRequestEvent *req; + XEvent respond; + + req=&(ev->xselectionrequest); + pthread_mutex_lock(©buf_mutex); + if(copybuf==NULL) { + respond.xselection.property=None; + } + else { + if(req->target==XA_STRING) { + x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf)); + respond.xselection.property=req->property; + } + else + respond.xselection.property=None; + } + respond.xselection.type=SelectionNotify; + respond.xselection.display=req->display; + respond.xselection.requestor=req->requestor; + respond.xselection.selection=req->selection; + respond.xselection.target=req->target; + respond.xselection.time=req->time; + x11.XSendEvent(dpy,req->requestor,0,0,&respond); + pthread_mutex_unlock(©buf_mutex); + } + break; + + /* Mouse Events */ + case MotionNotify: + { + XMotionEvent *me = (XMotionEvent *)ev; + + me->x/=vstat.scaling; + me->x/=vstat.charwidth; + me->y/=vstat.scaling; + me->y/=vstat.charheight; + me->x++; + me->y++; + if(me->x<1) + me->x=1; + if(me->y<1) + me->y=1; + if(me->x>vstat.cols) + me->x=vstat.cols; + if(me->y>vstat.rows+1) + me->y=vstat.rows+1; + ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y); + } + break; + case ButtonRelease: + { + XButtonEvent *be = (XButtonEvent *)ev; + + be->x/=vstat.scaling; + be->x/=vstat.charwidth; + be->y/=vstat.scaling; + be->y/=vstat.charheight; + be->x++; + be->y++; + if(be->x<1) + be->x=1; + if(be->y<1) + be->y=1; + if(be->x>vstat.cols) + be->x=vstat.cols; + if(be->y>vstat.rows+1) + be->y=vstat.rows+1; + if (be->button <= 3) { + ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y); + } + } + break; + case ButtonPress: + { + XButtonEvent *be = (XButtonEvent *)ev; + + be->x/=vstat.scaling; + be->x/=vstat.charwidth; + be->y/=vstat.scaling; + be->y/=vstat.charheight; + be->x++; + be->y++; + if(be->x<1) + be->x=1; + if(be->y<1) + be->y=1; + if(be->x>vstat.cols) + be->x=vstat.cols; + if(be->y>vstat.rows+1) + be->y=vstat.rows+1; + if (be->button <= 3) { + ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y); + } + } + break; + + /* Keyboard Events */ + case KeyPress: + { + static char buf[128]; + KeySym ks; + int n; + int nlock = 0; + WORD scan = 0xffff; + + n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0); + + switch (ks) { + + case XK_Escape: + scan = 1; + goto docode; + + case XK_Tab: + case XK_ISO_Left_Tab: + scan = 15; + goto docode; + + case XK_Return: + case XK_KP_Enter: + scan = 28; + goto docode; + + case XK_Print: + scan = 55; + goto docode; + + case XK_F1: + case XK_F2: + case XK_F3: + case XK_F4: + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F8: + case XK_F9: + case XK_F10: + scan = ks - XK_F1 + 59; + goto docode; + + case XK_KP_7: + nlock = 1; + case XK_Home: + case XK_KP_Home: + scan = 71; + goto docode; + + case XK_KP_8: + nlock = 1; + case XK_Up: + case XK_KP_Up: + scan = 72; + goto docode; + + case XK_KP_9: + nlock = 1; + case XK_Prior: + case XK_KP_Prior: + scan = 73; + goto docode; + + case XK_KP_Subtract: + scan = 74; + goto docode; + + case XK_KP_4: + nlock = 1; + case XK_Left: + case XK_KP_Left: + scan = 75; + goto docode; + + case XK_KP_5: + nlock = 1; + case XK_Begin: + case XK_KP_Begin: + scan = 76; + goto docode; + + case XK_KP_6: + nlock = 1; + case XK_Right: + case XK_KP_Right: + scan = 77; + goto docode; + + case XK_KP_Add: + scan = 78; + goto docode; + + case XK_KP_1: + nlock = 1; + case XK_End: + case XK_KP_End: + scan = 79; + goto docode; + + case XK_KP_2: + nlock = 1; + case XK_Down: + case XK_KP_Down: + scan = 80; + goto docode; + + case XK_KP_3: + nlock = 1; + case XK_Next: + case XK_KP_Next: + scan = 81; + goto docode; + + case XK_KP_0: + nlock = 1; + case XK_Insert: + case XK_KP_Insert: + scan = 82; + goto docode; + + case XK_KP_Decimal: + nlock = 1; + scan = 83; + goto docode; + + case XK_Delete: + case XK_KP_Delete: + /* scan = flipdelete ? 14 : 83; */ + scan = 83; + goto docode; + + case XK_BackSpace: + /* scan = flipdelete ? 83 : 14; */ + scan = 14; + goto docode; + + case XK_F11: + scan = 87; + goto docode; + case XK_F12: + scan = 88; + goto docode; + + + case XK_KP_Divide: + scan = Ascii2Scan['/']; + goto docode; + + case XK_KP_Multiply: + scan = Ascii2Scan['*']; + goto docode; + + default: + if (ks < ' ' || ks > '~') + break; + scan = Ascii2Scan[ks]; + docode: + if (nlock) + scan |= 0x100; + + if ((scan & ~0x100) > 88) { + scan = 0xffff; + break; + } + + if ((ev->xkey.state & ShiftMask) || (scan & 0x100)) { + scan = ScanCodes[scan & 0xff].shift; + } else if (ev->xkey.state & ControlMask) { + scan = ScanCodes[scan & 0xff].ctrl; + } else if (ev->xkey.state & Mod1Mask) { + scan = ScanCodes[scan & 0xff].alt; + } else + scan = ScanCodes[scan & 0xff].base; + + break; + } + if (scan != 0xffff) { + unsigned char ch; + ch=scan & 0xff; + write(key_pipe[1], &ch, 1); + if(!ch) { + ch=scan >> 8; + write(key_pipe[1], &ch, 1); + } + } + return(1); + } + default: + break; + } + return(0); +} + +void x11_event_thread(void *args) +{ + int x; + int high_fd; + fd_set fdset; + XEvent ev; + static struct timeval tv; + + if(video_init()) { + sem_post(&init_complete); + return; + } + initialized=1; + sem_post(&init_complete); + + if(local_pipe[0] > xfd) + high_fd=local_pipe[0]; + else + high_fd=xfd; + + for (;;) { + tv.tv_sec=0; + tv.tv_usec=54925; /* was 54925 (was also 10) */ + + /* + * Handle any events just sitting around... + */ + while (QLength(dpy) > 0) { + x11.XNextEvent(dpy, &ev); + x11_event(&ev); + } + + FD_ZERO(&fdset); + FD_SET(xfd, &fdset); + FD_SET(local_pipe[0], &fdset); + + x = select(high_fd+1, &fdset, 0, 0, &tv); + + switch (x) { + case -1: + /* + * Errno might be wrong, so we just select again. + * This could cause a problem is something really + * was wrong with select.... + */ + + /* perror("select"); */ + break; + case 0: + /* Timeout */ + break; + default: + if (FD_ISSET(xfd, &fdset)) { + x11.XNextEvent(dpy, &ev); + x11_event(&ev); + } + while(FD_ISSET(local_pipe[0], &fdset)) { + struct x11_local_event lev; + + read(local_pipe[0], &lev, sizeof(lev)); + switch(lev.type) { + case X11_LOCAL_SETMODE: + init_mode(lev.data.mode); + break; + case X11_LOCAL_SETNAME: + x11.XSetIconName(dpy, win, lev.data.name); + x11.XFlush(dpy); + break; + case X11_LOCAL_SETTITLE: + x11.XStoreName(dpy, win, lev.data.title); + x11.XFlush(dpy); + break; + case X11_LOCAL_COPY: + x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime); + break; + case X11_LOCAL_PASTE: + { + Window sowner=None; + + sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD); + if(sowner==win) { + /* Get your own primary selection */ + if(copybuf==NULL) + pastebuf=NULL; + else + pastebuf=strdup(copybuf); + /* Set paste buffer */ + sem_post(&pastebuf_set); + sem_wait(&pastebuf_used); + FREE_AND_NULL(pastebuf); + } + else if(sowner!=None) { + x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, None, win, CurrentTime); + } + else { + /* Set paste buffer */ + pastebuf=NULL; + sem_post(&pastebuf_set); + sem_wait(&pastebuf_used); + } + } + break; + case X11_LOCAL_DRAWRECT: + local_draw_rect(&lev.data.rect); + break; + case X11_LOCAL_BEEP: + x11.XBell(dpy, 100); + break; + } + tv.tv_sec=0; + tv.tv_usec=0; + + FD_ZERO(&fdset); + FD_SET(local_pipe[0], &fdset); + + if(select(local_pipe[0]+1, &fdset, 0, 0, &tv)!=1) + FD_ZERO(&fdset); + } + } + } +} diff --git a/src/conio/x_events.h b/src/conio/x_events.h new file mode 100644 index 0000000000000000000000000000000000000000..75feac3b3cd7d1a88d8a2f9e428d392ecdf0ce63 --- /dev/null +++ b/src/conio/x_events.h @@ -0,0 +1,104 @@ +#ifndef _X_EVENTS_H_ +#define _X_EVENTS_H_ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> + +struct update_rect { + int x; + int y; + int width; + int height; + unsigned char *data; +}; + +enum x11_local_events { + X11_LOCAL_SETMODE + ,X11_LOCAL_SETNAME + ,X11_LOCAL_SETTITLE + ,X11_LOCAL_COPY + ,X11_LOCAL_PASTE + ,X11_LOCAL_DRAWRECT + ,X11_LOCAL_BEEP +}; + +struct x11_local_event { + enum x11_local_events type; + union { + int mode; + char name[81]; + char title[81]; + struct update_rect rect; + } data; +}; + +/* X functions */ +struct x11 { + int (*XChangeGC) (Display*, GC, unsigned long, XGCValues*); + int (*XCopyPlane) (Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long); + int (*XFillRectangle) (Display*, Drawable, GC, int, int, unsigned int, unsigned int); + int (*XDrawPoint) (Display*, Drawable, GC, int, int); + int (*XFlush) (Display*); + int (*XSync) (Display*, Bool); + int (*XBell) (Display*, int); + int (*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*); + int (*XNextEvent) (Display*, XEvent *); + XSizeHints* (*XAllocSizeHints)(void); + void (*XSetWMNormalHints) (Display*, Window, XSizeHints*); + int (*XResizeWindow)(Display*, Window, unsigned int, unsigned int); + int (*XMapWindow) (Display*, Window); + int (*XFree) (void *data); + int (*XFreePixmap) (Display*, Pixmap); + Pixmap (*XCreatePixmap)(Display*, Drawable, unsigned int, unsigned int, unsigned int); + void (*XCopyArea) (Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int); + Pixmap (*XCreateBitmapFromData) (Display*, Drawable, _Xconst char*, unsigned int, unsigned int); + Status (*XAllocColor) (Display*, Colormap, XColor*); + Display*(*XOpenDisplay) (_Xconst char*); + Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); + GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*); + int (*XSelectInput) (Display*, Window, long); + int (*XStoreName) (Display*, Window, _Xconst char*); + Window (*XGetSelectionOwner) (Display*, Atom); + int (*XConvertSelection) (Display*, Atom, Atom, Atom, Window, Time); + int (*XGetWindowProperty) (Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **); + int (*XChangeProperty) (Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int); + Status (*XSendEvent) (Display*, Window, Bool, long, XEvent*); + XImage* (*XCreateImage) (Display *, Visual *, unsigned int, int, int, char *,unsigned int, unsigned int, int, int); +#ifndef XPutPixel + void (*XPutPixel) (XImage*,int,int,unsigned long); +#endif + void (*XPutImage) (Display*, Drawable, GC, XImage *, int,int,int,int,unsigned int,unsigned int); +#ifndef XDestroyImage + void (*XDestroyImage)(XImage*); +#endif + int (*XSetSelectionOwner) (Display*, Atom, Window, Time); + int (*XSetIconName) (Display*, Window, _Xconst char *); + int (*XSynchronize) (Display*, Bool); + Status (*XGetWindowAttributes) (Display*,Window,XWindowAttributes*); +}; + + + +extern int local_pipe[2]; /* Used for passing local events */ +extern int key_pipe[2]; /* Used for passing keyboard events */ + +extern struct x11 x11; + +extern char *copybuf; +extern pthread_mutex_t copybuf_mutex; +extern char *pastebuf; +extern sem_t pastebuf_set; +extern sem_t pastebuf_used; +extern sem_t init_complete; +extern sem_t mode_set; +extern int x11_window_xpos; +extern int x11_window_ypos; +extern int x11_window_width; +extern int x11_window_height; +extern int initialized; + +void x11_event_thread(void *args); + +#endif