]> git.webhop.me Git - lcd4linux.git/commitdiff
[lcd4linux @ 2003-02-18 06:13:44 by reinelt]
authorreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Tue, 18 Feb 2003 06:13:44 +0000 (06:13 +0000)
committerreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Tue, 18 Feb 2003 06:13:44 +0000 (06:13 +0000)
X11 driver fixes and cleanup

git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@181 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

README.X11
XWindow.c

index 7b5562425a3ceb4ab148ddc9a8c1fc6986c5267b..0fb3dbfcfd0446ead4708995f9efbda3fa05ab24 100644 (file)
@@ -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.
 
index c16155c334d7441587a1a6853d4ec2a99938dd28..90c9c9918c569941aab961960b0dcb44cd60fb3d 100644 (file)
--- a/XWindow.c
+++ b/XWindow.c
@@ -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
  *
 #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 }
 };