diff options
author | reinelt <> | 2003-02-18 06:13:44 +0000 |
---|---|---|
committer | reinelt <> | 2003-02-18 06:13:44 +0000 |
commit | c276b1c1bb264a147a8646e79e18e26c3ef52000 (patch) | |
tree | c0106d80e362112f449da5ac157d2d939eef8815 | |
parent | cd113ac099ae3d466a31bb8e34134a4458928f4b (diff) | |
download | lcd4linux-c276b1c1bb264a147a8646e79e18e26c3ef52000.tar.gz |
[lcd4linux @ 2003-02-18 06:13:44 by reinelt]
X11 driver fixes and cleanup
-rw-r--r-- | README.X11 | 4 | ||||
-rw-r--r-- | XWindow.c | 652 |
2 files changed, 327 insertions, 329 deletions
@@ -1,5 +1,5 @@ # -# $Id: README.X11,v 1.2 2000/04/03 04:46:38 reinelt Exp $ +# $Id: README.X11,v 1.3 2003/02/18 06:13:44 reinelt Exp $ # This is the README file for the X11 display driver for lcd4linux @@ -34,7 +34,7 @@ pixelsize*pixelsize pixels. If you want to, you can emulate the gap between this lcd cells by specifying a pixelgap greater than zero. Sometimes there's a gap between characters, too. You can specify this gap (in pixels again) horizontally and vertically. Usually this gap -is the same size as a cell (which is pixelsize+pixelgap). If you specify +is the same size as a cell (which is pixelsize+pixelgap). If you specify either the row gap or the column gap as -1, this cell size will be used instead. @@ -1,4 +1,4 @@ -/* $Id: XWindow.c,v 1.28 2003/02/17 06:06:12 reinelt Exp $ +/* $Id: XWindow.c,v 1.29 2003/02/18 06:13:44 reinelt Exp $ * * X11 Driver for LCD4Linux * @@ -20,6 +20,9 @@ * * * $Log: XWindow.c,v $ + * Revision 1.29 2003/02/18 06:13:44 reinelt + * X11 driver fixes and cleanup + * * Revision 1.28 2003/02/17 06:06:12 reinelt * small bug in X11 driver: omit pixel gap between cahracters * @@ -152,6 +155,7 @@ #include "bar.h" #include "pixmap.h" + /* glibc 2.1 requires defining semun ourselves */ #ifdef _SEM_SEMUN_UNDEFINED union semun { @@ -162,7 +166,6 @@ union semun { }; #endif -#define BARS ( BAR_L | BAR_R | BAR_U | BAR_D | BAR_H2 | BAR_V2 | BAR_T) static LCD Lcd; static Display *dp; @@ -175,7 +178,7 @@ static GC gc,gcb,gch; static XColor co[3]; static Pixmap pmback; -static unsigned char *BackupLCDpixmap; +static unsigned char *LCDpixmap2; static char *rgbfg,*rgbbg,*rgbhg; static int pixel=-1; /*pointsize in pixel*/ static int pgap=0; /*gap between points */ @@ -192,374 +195,369 @@ static int semid=-1; static int shmid=-1; static int ppid; /*parent pid*/ -static void acquire_lock() { -struct sembuf sembuf; - sembuf.sem_num=0; - sembuf.sem_op=-1; - sembuf.sem_flg=0; - semop(semid,&sembuf,1); /* get mutex */ + +static void acquire_lock() +{ + struct sembuf sembuf; + sembuf.sem_num=0; + sembuf.sem_op=-1; + sembuf.sem_flg=0; + semop(semid,&sembuf,1); /* get mutex */ } -static void release_lock() { -struct sembuf sembuf; - sembuf.sem_num=0; - sembuf.sem_op=1; - sembuf.sem_flg=0; - semop(semid,&sembuf,1); /* free mutex */ + +static void release_lock() +{ + struct sembuf sembuf; + sembuf.sem_num=0; + sembuf.sem_op=1; + sembuf.sem_flg=0; + semop(semid,&sembuf,1); /* free mutex */ } -static void semcleanup() { -union semun arg; - if (semid>-1) semctl(semid,0,IPC_RMID,arg); + +static void semcleanup() +{ + union semun arg; + if (semid>-1) semctl(semid,0,IPC_RMID,arg); } -static void shmcleanup() { - if (shmid>-1) shmctl(shmid,IPC_RMID,NULL); + +static void shmcleanup() +{ + if (shmid>-1) shmctl(shmid,IPC_RMID,NULL); } -static void quit_updater() { -int i; - if (async_updater_pid>1) { - i=async_updater_pid; - async_updater_pid=1; - kill(i,9); - waitpid(i,&i,0); - } + +static void quit_updater() +{ + int i; + if (async_updater_pid>1) { + i=async_updater_pid; + async_updater_pid=1; + kill(i,9); + waitpid(i,&i,0); + } } -static void sig_updater(int sig) { - kill(ppid,sig); - exit(0); + +static void sig_updater(int sig) +{ + kill(ppid,sig); + exit(0); } -static void init_signals() { -unsigned int ignsig=(1<<SIGBUS)|(1<<SIGFPE)|(1<<SIGSEGV)| - (1<<SIGTSTP)|(1<<SIGCHLD)|(1<<SIGCONT)| - (1<<SIGTTIN)|(1<<SIGWINCH); -int i; - for(i=0;i<NSIG;i++) - if (((1<<i)&ignsig)==0) - signal(i,sig_updater); +static void init_signals() +{ + unsigned int ignsig=(1<<SIGBUS)|(1<<SIGFPE)|(1<<SIGSEGV)| + (1<<SIGTSTP)|(1<<SIGCHLD)|(1<<SIGCONT)| + (1<<SIGTTIN)|(1<<SIGWINCH); + int i; + for(i=0;i<NSIG;i++) + if (((1<<i)&ignsig)==0) + signal(i,sig_updater); + } -static int init_shm(int nbytes,unsigned char **buf) { - - shmid=shmget(IPC_PRIVATE,nbytes,SHM_R|SHM_W); - if (shmid==-1) { - error ("X11: shmget() failed: %s", strerror(errno)); - return -1; - } - *buf=shmat(shmid,NULL,0); - if (*buf==NULL) { - error ("X11: shmat() failed: %s", strerror(errno)); - return -1; - } - return 0; + +static int init_shm(int nbytes,unsigned char **buf) +{ + shmid=shmget(IPC_PRIVATE,nbytes,SHM_R|SHM_W); + if (shmid==-1) { + error ("X11: shmget() failed: %s", strerror(errno)); + return -1; + } + *buf=shmat(shmid,NULL,0); + if (*buf==NULL) { + error ("X11: shmat() failed: %s", strerror(errno)); + return -1; + } + return 0; } -static int init_thread(int bufsiz) { -union semun semun; /* acording to SUN-Solaris man-pages: */ - -#define SEM_ALTER 0200 - - semid=semget(IPC_PRIVATE,1,SEM_ALTER); - if (semid==-1) { - error ("X11: semget() failed: %s", strerror(errno)); - return -1; - } - semun.val=1; - semctl(semid,0,SETVAL,semun); - - ppid=getpid(); - switch(async_updater_pid=fork()) { - case -1: - error ("X11: fork() failed: %s", strerror(errno)); - return -1; - case 0: - async_update(); - error ("X11: async_update failed"); - kill(ppid,SIGTERM); - exit(-1); - default: - break; - } - signal(SIGCHLD,quit_updater); - atexit(quit_updater); - return 0; +#define SEM_ALTER 0200 + +static int init_thread(int bufsiz) +{ + union semun semun; + + semid=semget(IPC_PRIVATE,1,SEM_ALTER); + if (semid==-1) { + error ("X11: semget() failed: %s", strerror(errno)); + return -1; + } + semun.val=1; + semctl(semid,0,SETVAL,semun); + + ppid=getpid(); + switch(async_updater_pid=fork()) { + case -1: + error ("X11: fork() failed: %s", strerror(errno)); + return -1; + case 0: + async_update(); + error ("X11: async_update failed"); + kill(ppid,SIGTERM); + exit(-1); + default: + break; + } + signal(SIGCHLD,quit_updater); + atexit(quit_updater); + return 0; } -static int init_x(int rows,int cols,int xres,int yres) { -XSetWindowAttributes wa; -XSizeHints size_hints; -XColor co_dummy; -XEvent ev; - - if ((dp=XOpenDisplay(NULL))==NULL) { - error ("X11: can't open display"); - return -1; - } - sc=DefaultScreen(dp); - gc=DefaultGC(dp,sc); - vi=DefaultVisual(dp,sc); - dd=DefaultDepth(dp,sc); - rw=DefaultRootWindow(dp); - cm=DefaultColormap(dp,sc); - - if (XAllocNamedColor(dp,cm,rgbfg,&co[0],&co_dummy)==False) { - error ("X11: can't alloc foreground color '%s'", - rgbfg); - return -1; - } - if (XAllocNamedColor(dp,cm,rgbbg,&co[1],&co_dummy)==False) { - error ("X11: can't alloc background color '%s'", - rgbbg); - return -1; - } - if (XAllocNamedColor(dp,cm,rgbhg,&co[2],&co_dummy)==False) { - error ("X11: can't alloc halfground color '%s'", - rgbhg); - return -1; - } - boxw=xres*pixel+(xres-1)*pgap+cgap; - boxh=yres*pixel+(yres-1)*pgap+rgap; - dimx=cols*xres*pixel+cols*(xres-1)*pgap+(cols-1)*cgap; - dimy=rows*yres*pixel+rows*(yres-1)*pgap+(rows-1)*rgap; - wa.event_mask=ExposureMask; - w=XCreateWindow(dp,rw,0,0,dimx+2*border,dimy+2*border,0,0, - InputOutput,vi,CWEventMask,&wa); - pmback=XCreatePixmap(dp,w,dimx,dimy,dd); - size_hints.min_width=size_hints.max_width=dimx+2*border; - size_hints.min_height=size_hints.max_height=dimy+2*border; - size_hints.flags=PPosition|PSize|PMinSize|PMaxSize; - XSetWMProperties(dp,w,NULL,NULL,NULL,0,&size_hints,NULL,NULL); - XSetForeground(dp,gc,co[0].pixel); - XSetBackground(dp,gc,co[1].pixel); - gcb=XCreateGC(dp,w,0,NULL); - XSetForeground(dp,gcb,co[1].pixel); - XSetBackground(dp,gcb,co[0].pixel); - gch=XCreateGC(dp,w,0,NULL); - XSetForeground(dp,gch,co[2].pixel); - XSetBackground(dp,gch,co[0].pixel); - XFillRectangle(dp,pmback,gcb,0,0,dimx,dimy); - XSetWindowBackground(dp,w,co[1].pixel); - XClearWindow(dp,w); - XStoreName(dp,w,"XLCD4Linux"); - XMapWindow(dp,w); - XFlush(dp); - for(;;) { - XNextEvent(dp,&ev); - if (ev.type==Expose && ev.xexpose.count==0) - break; - } - return 0; + +static int init_x(int rows,int cols,int xres,int yres) +{ + XSetWindowAttributes wa; + XSizeHints size_hints; + XColor co_dummy; + XEvent ev; + + if ((dp=XOpenDisplay(NULL))==NULL) { + error ("X11: can't open display"); + return -1; + } + sc=DefaultScreen(dp); + gc=DefaultGC(dp,sc); + vi=DefaultVisual(dp,sc); + dd=DefaultDepth(dp,sc); + rw=DefaultRootWindow(dp); + cm=DefaultColormap(dp,sc); + + if (XAllocNamedColor(dp,cm,rgbfg,&co[0],&co_dummy)==False) { + error ("X11: can't alloc foreground color '%s'", + rgbfg); + return -1; + } + if (XAllocNamedColor(dp,cm,rgbbg,&co[1],&co_dummy)==False) { + error ("X11: can't alloc background color '%s'", + rgbbg); + return -1; + } + if (XAllocNamedColor(dp,cm,rgbhg,&co[2],&co_dummy)==False) { + error ("X11: can't alloc halfground color '%s'", + rgbhg); + return -1; + } + boxw=xres*pixel+(xres-1)*pgap+cgap; + boxh=yres*pixel+(yres-1)*pgap+rgap; + dimx=cols*xres*pixel+(cols*xres-1)*pgap+(cols-1)*cgap; + dimy=rows*yres*pixel+(rows*yres-1)*pgap+(rows-1)*rgap; + wa.event_mask=ExposureMask; + w=XCreateWindow(dp,rw,0,0,dimx+2*border,dimy+2*border,0,0, + InputOutput,vi,CWEventMask,&wa); + pmback=XCreatePixmap(dp,w,dimx,dimy,dd); + size_hints.min_width=size_hints.max_width=dimx+2*border; + size_hints.min_height=size_hints.max_height=dimy+2*border; + size_hints.flags=PPosition|PSize|PMinSize|PMaxSize; + XSetWMProperties(dp,w,NULL,NULL,NULL,0,&size_hints,NULL,NULL); + XSetForeground(dp,gc,co[0].pixel); + XSetBackground(dp,gc,co[1].pixel); + gcb=XCreateGC(dp,w,0,NULL); + XSetForeground(dp,gcb,co[1].pixel); + XSetBackground(dp,gcb,co[0].pixel); + gch=XCreateGC(dp,w,0,NULL); + XSetForeground(dp,gch,co[2].pixel); + XSetBackground(dp,gch,co[0].pixel); + XFillRectangle(dp,pmback,gcb,0,0,dimx,dimy); + XSetWindowBackground(dp,w,co[1].pixel); + XClearWindow(dp,w); + XStoreName(dp,w,"XLCD4Linux"); + XMapWindow(dp,w); + XFlush(dp); + for(;;) { + XNextEvent(dp,&ev); + if (ev.type==Expose && ev.xexpose.count==0) + break; + } + return 0; } -int xlcdinit(LCD *Self) { -char *s; - - if (sscanf(s=cfg_get("size")?:"20x4","%dx%d",&cols,&rows)!=2 - || rows<1 || cols<1) { - error ("X11: bad size '%s'",s); - return -1; - } - if (sscanf(s=cfg_get("font")?:"5x8","%dx%d",&xres,&yres)!=2 - || xres<5 || yres>10) { - error ("X11: bad font '%s'",s); - return -1; - } - if (sscanf(s=cfg_get("pixel")?:"4+1","%d+%d",&pixel,&pgap)!=2 - || pixel<1 || pgap<0) { - error ("X11: bad pixel '%s'",s); - return -1; - } - if (sscanf(s=cfg_get("gap")?:"3x3","%dx%d",&cgap,&rgap)!=2 - || cgap<-1 || rgap<-1) { - error ("X11: bad gap '%s'",s); - return -1; - } - if (rgap<0) rgap=pixel+pgap; - if (cgap<0) cgap=pixel+pgap; - border=atoi(cfg_get("border")?:"0"); - rgbfg=cfg_get("foreground")?:"#000000"; - rgbbg=cfg_get("background")?:"#80d000"; - rgbhg=cfg_get("halfground")?:"#70c000"; - if (*rgbfg=='\\') rgbfg++; - if (*rgbbg=='\\') rgbbg++; - if (*rgbhg=='\\') rgbhg++; - - if (pix_init(rows,cols,xres,yres)==-1) return -1; - if (init_x(rows,cols,xres,yres)==-1) return -1; - init_signals(); - if (init_shm(rows*cols*xres*yres,&BackupLCDpixmap)==-1) return -1; - memset(BackupLCDpixmap,0xff,rows*yres*cols*xres); - if (init_thread(rows*cols*xres*yres)==-1) return -1; - Self->rows=rows; - Self->cols=cols; - Self->xres=xres; - Self->yres=yres; - Lcd=*Self; - - pix_clear(); - return 0; + +int xlcdinit(LCD *Self) +{ + char *s; + + if (sscanf(s=cfg_get("size")?:"20x4","%dx%d",&cols,&rows)!=2 + || rows<1 || cols<1) { + error ("X11: bad size '%s'",s); + return -1; + } + if (sscanf(s=cfg_get("font")?:"5x8","%dx%d",&xres,&yres)!=2 + || xres<5 || yres>10) { + error ("X11: bad font '%s'",s); + return -1; + } + if (sscanf(s=cfg_get("pixel")?:"4+1","%d+%d",&pixel,&pgap)!=2 + || pixel<1 || pgap<0) { + error ("X11: bad pixel '%s'",s); + return -1; + } + if (sscanf(s=cfg_get("gap")?:"3x3","%dx%d",&cgap,&rgap)!=2 + || cgap<-1 || rgap<-1) { + error ("X11: bad gap '%s'",s); + return -1; + } + if (rgap<0) rgap=pixel+pgap; + if (cgap<0) cgap=pixel+pgap; + border=atoi(cfg_get("border")?:"0"); + rgbfg=cfg_get("foreground")?:"#000000"; + rgbbg=cfg_get("background")?:"#80d000"; + rgbhg=cfg_get("halfground")?:"#70c000"; + if (*rgbfg=='\\') rgbfg++; + if (*rgbbg=='\\') rgbbg++; + if (*rgbhg=='\\') rgbhg++; + + if (pix_init(rows,cols,xres,yres)==-1) return -1; + if (init_x(rows,cols,xres,yres)==-1) return -1; + init_signals(); + if (init_shm(rows*cols*xres*yres,&LCDpixmap2)==-1) return -1; + memset(LCDpixmap2,0xff,rows*yres*cols*xres); + if (init_thread(rows*cols*xres*yres)==-1) return -1; + Self->rows=rows; + Self->cols=cols; + Self->xres=xres; + Self->yres=yres; + Lcd=*Self; + + pix_clear(); + return 0; } -int xlcdclear() { - return pix_clear(); + +int xlcdclear() +{ + return pix_clear(); } -int xlcdput(int row,int col,char *text) { - return pix_put(row,col,text); + +int xlcdput(int row,int col,char *text) +{ + return pix_put(row,col,text); } -int xlcdbar(int type, int row, int col, int max, int len1, int len2) { - return pix_bar(type,row,col,max,len1,len2); + +int xlcdbar(int type, int row, int col, int max, int len1, int len2) +{ + return pix_bar(type,row,col,max,len1,len2); } + int xlcdflush() { -int dirty; -int i,j,igap,jgap,pos; -int x,y; - - acquire_lock(); - dirty=pos=igap=jgap=0; - y=border; - for(i=0;i<rows*yres;i++) { - x=border; - for(j=0;j<cols*xres;j++) { - if (LCDpixmap[pos]^BackupLCDpixmap[pos]) { - XFillRectangle(dp,w, - LCDpixmap[pos]?gc:gch, - x,y, - pixel,pixel); - BackupLCDpixmap[pos]=LCDpixmap[pos]; - dirty=1; - } - x+=pixel+pgap; -#if 0 - // this is wrong! MR - if (++jgap==xres) { x+=cgap-pgap; jgap=0; } -#endif - pos++; - } - y+=pixel+pgap; - if (++igap==yres) { y+=rgap-pgap; igap=0; } - } - if (dirty) XSync(dp,False); - release_lock(); - return 0; + int dirty; + int row,col; + + acquire_lock(); + dirty=0; + for(row=0;row<rows*yres;row++) { + int y=border+(row/yres)*rgap+row*(pixel+pgap); + for(col=0;col<cols*xres;col++) { + int x=border+(col/xres)*cgap+col*(pixel+pgap); + int p=row*cols*xres+col; + if (LCDpixmap[p]^LCDpixmap2[p]) { + XFillRectangle(dp,w,LCDpixmap[p]?gc:gch,x,y,pixel,pixel); + LCDpixmap2[p]=LCDpixmap[p]; + dirty=1; + } + } + } + if (dirty) XSync(dp,False); + release_lock(); + return 0; } -int xlcdquit(void) { - error("xlcdquit"); - semcleanup(); - shmcleanup(); - quit_updater(); - return 0; + +int xlcdquit(void) +{ + semcleanup(); + shmcleanup(); + quit_updater(); + return 0; } + /* * this one should only be called from the updater-thread * no user serviceable parts inside */ -static void update(int x,int y,int width,int height) { -int i,j,igap,jgap,wjgap,pos,wpos,xpix; -int xfrom,yfrom; -int xto,yto; -int dx,wx,wy; - - /* - * theory of operation: - * f:bitpos->pxnr*(pixel+pgap)+(pxnr/xres)*cgap; - * f^-1: pxnr -> f^-1(bitpos) = see paper - */ - x-=border; - y-=border; - if (x>=dimx || y>=dimy || x+width<0 || y+height<0) - return; /*border doesnt need update*/ - if (x<0) x=0; - if (y<0) y=0; - if (x+width>dimx) width=dimx-x; - if (y+height>dimy) height=dimy-y; - /* - * now we have to find out where the box starts - * with respects to the LCDpixmap coordinates - */ - /* upper left corner */ - xfrom=xres*(x/boxw); /*start at col.no*/ - i=(x%boxw); /*pixelpos rel. char*/ - if (i>xres*pixel+(xres-1)*pgap) /*in cgap zone*/ - xfrom+=xres; - else { - xfrom+=i/(pixel+pgap); /*character element*/ - if (i%(pixel+pgap)>=pixel) /*in pgap zone*/ - xfrom++; - } - yfrom=yres*(y/boxh); /*start at row.no*/ - i=(y%boxh); /*pixelpos rel. char*/ - if (i>yres*pixel+(yres-1)*pgap) /*in rgap zone*/ - yfrom+=yres; - else { - yfrom+=i/(pixel+pgap); /*character element*/ - if (i%(pixel+pgap)>=pixel) /*in pgag zone*/ - yfrom++; - } - /*lower right corner*/ - x+=width-1; - y+=height-1; - xto=xres*(x/boxw)+(x%boxw)/(pixel+pgap); - yto=yres*(y/boxh)+(y%boxh)/(pixel+pgap); - - pos=yfrom*xres*cols+xfrom; - wy=border+yfrom*(pixel+pgap)+(yfrom/yres)*(rgap-pgap); - wx=border+xfrom*(pixel+pgap)+(xfrom/xres)*(cgap-pgap); - wpos=pos; xpix=xres*cols; - igap=yfrom%yres; wjgap=xfrom%xres; - for(i=yfrom;i<=yto;i++) { - dx=wx; - jgap=wjgap; - for(j=xfrom;j<=xto;j++) { - XFillRectangle(dp,w, - BackupLCDpixmap[wpos++]?gc:gch, - dx,wy, - pixel,pixel); - dx+=pixel+pgap; -#if 0 - // this is wrong! MR - if (++jgap==xres) { dx+=cgap-pgap; jgap=0; } -#endif - } - wy+=pixel+pgap; - if (++igap==yres) { wy+=rgap-pgap; igap=0; } - pos+=xpix; - wpos=pos; - } - XSync(dp,False); +static void update(int x,int y,int width,int height) +{ + /* + * theory of operation: + * instead of the old, fully-featured but complicated update + * region calculation, we do an update of the whole display, + * but check before every pixel if the pixel region is inside + * the update region. + */ + + int x0, y0; + int x1, y1; + int row, col; + int dirty; + + x0=x-pixel; + y0=y-pixel; + x1=x+pixel+width; + y1=y+pixel+height; + + dirty=0; + for(row=0;row<rows*yres;row++) { + int y=border+(row/yres)*rgap+row*(pixel+pgap); + if (y<y0 || y>y1) continue; + for(col=0;col<cols*xres;col++) { + int x=border+(col/xres)*cgap+col*(pixel+pgap); + if (x<x0 || x>x1) continue; + int p=row*cols*xres+col; + XFillRectangle(dp,w,LCDpixmap2[p]?gc:gch,x,y,pixel,pixel); + dirty=1; + } + } + if (dirty) XSync(dp,False); } -static int async_update() { -XSetWindowAttributes wa; -XEvent ev; - - if ((dp=XOpenDisplay(NULL))==NULL) - return -1; - wa.event_mask=ExposureMask; - XChangeWindowAttributes(dp,w,CWEventMask,&wa); - for(;;) { - XWindowEvent(dp,w,ExposureMask,&ev); - if (ev.type==Expose) { - acquire_lock(); - update(ev.xexpose.x,ev.xexpose.y, - ev.xexpose.width,ev.xexpose.height); - release_lock(); - } - } + +static int async_update() +{ + XSetWindowAttributes wa; + XEvent ev; + + if ((dp=XOpenDisplay(NULL))==NULL) + return -1; + wa.event_mask=ExposureMask; + XChangeWindowAttributes(dp,w,CWEventMask,&wa); + for(;;) { + XWindowEvent(dp,w,ExposureMask,&ev); + if (ev.type==Expose) { + acquire_lock(); + update(ev.xexpose.x,ev.xexpose.y, + ev.xexpose.width,ev.xexpose.height); + release_lock(); + } + } } + LCD XWindow[] = { - { "X11",0,0,0,0,BARS,0,xlcdinit,xlcdclear,xlcdput,xlcdbar,NULL,xlcdflush,xlcdquit }, - { NULL } + { name: "X11", + rows: 0, + cols: 0, + xres: 0, + yres: 0, + bars: BAR_L | BAR_R | BAR_U | BAR_D | BAR_H2 | BAR_V2 | BAR_T, + gpos: 0, + init: xlcdinit, + clear: xlcdclear, + put: xlcdput, + bar: xlcdbar, + gpo: NULL, + flush: xlcdflush, + quit: xlcdquit + }, + { NULL } }; |