[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Next version : Improved X11 performance for xlinrad wit MIT-SHM



Hi Leif,

On Fri, 2009-07-24 at 14:47 +0200, Leif Asbrink wrote:

> OK. I have packed the current version in the attached file. Please start
> from that to make it easier to merge the code you make with the changes I
> make myself.
>  
I made the following modifications:

1. All MIT-SHM code is enclosed between  #if SHM_INSTALLED == 1 and
#endif statements to avoid compilation errors when the MIT-SHM libraries
are not available.

2. In xmain.c at line 118, I modified the content of the message:
It is possible that the X11 server does not support MIT-SHM calls
because the MIT-SHM option in the server was not enabled. 
In my opinion the lack of support for MIT-SHM calls by the X11 server
is not related to the availability of the packages libxext-dev and
x11proto-xext-dev on the linux system.

What do you think?

73

Pierre

// For help on X11 give command: "man X Interface"
// Event masks and event definitions are in /usr/X11R6/include/X11/X.h


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <ctype.h>
#include <semaphore.h>
#include <unistd.h>
#include <pthread.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include "globdef.h"
#include "thrdef.h"
#include "uidef.h"
#include "screendef.h"
#include "vernr.h"
#include "options.h"
#include "keyboard_def.h"
#include "lconf.h"
#include "xdef.h"
#include "ldef.h"

#if SHM_INSTALLED == 1
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>

extern XShmSegmentInfo *shminfo;
int ShmMajor,ShmMinor;
Bool ShmPixmaps;
#endif

extern GC xgc;
extern XImage *ximage;
extern Display *xdis;
extern Window xwin;
extern Colormap lir_colormap;

int newcomer_escflag;

typedef struct {
unsigned short int red;
unsigned short int green;
unsigned short int blue;
unsigned int pixel;
short int flag;
float total;
}PIXINFO;

// We want to know about the user clicking on the close window button
Atom wm_delete_window;

int main(int argc, char **argv)
{
int id,il,kd,kl;
int bitmap_pad;
float t1,t2;
PIXINFO *defpix, *lirpix;
float *pixdiff;
PIXINFO tmppix;
Colormap default_colormap;
char *hostname;
Visual *visual;
int i, k, m, screen_num;
Cursor cross_cursor;
unsigned short int *ipalette;
XColor xco;
for(i=0; i<MAX_LIRSEM; i++)lirsem_flag[i]=0;
XInitThreads();
if(DUMPFILE)
  {
  dmp = fopen("dmp", "w");
  DEB"\n******************************\n");
  }
else
  {  
  dmp=NULL;
  }
expose_event_done=FALSE;
first_mempix=0x7fffffff;
last_mempix=0;
shift_key_status=0;
i=argc;
os_flag=OS_FLAG_X;
init_os_independent_globals();
newcomer_escflag=FALSE;
serport=-1;
keyboard_buffer_ptr=0;
keyboard_buffer_used=0;
keyboard_buffer=malloc(KEYBOARD_BUFFER_SIZE*sizeof(int));
if (argv[1] == NULL)
  {
  hostname = NULL;
  }
else
  {
  hostname = argv[1];
  }
xdis = XOpenDisplay(hostname);
if (xdis == NULL)
  {
  fprintf(stderr, "\nCan't open display: %s\n", hostname);
  return(10);
  }
X11_accesstype=X11_STANDARD;
#if SHM_INSTALLED == 1
// test if the X11 server supports MIT-SHM
if(XShmQueryVersion(xdis,&ShmMajor,&ShmMinor,&ShmPixmaps))
  {
  X11_accesstype=X11_MIT_SHM;
  printf("\nThe X11 server supports MIT-SHM\n");
  }
else
  {
  printf("\nThe X11 server does not support MIT-SHM \n");
  printf("Check your X11 configuration with the xdpyinfo command \n");
  printf("and try to enable MIT-SHM  by adding following lines\n");
  printf("to the /etc/X11/xorg.conf file :\n\n");
  printf("Section ""Extensions"" \n");
  printf("       Option ""MIT-SHM"" ""enable""  \n");
  printf("EndSection \n\n");

//  printf("Suggest install packages libxext-dev and x11proto-xext-dev\n");
//  printf("Then ./configure and after that make xlinrad");
  }
#endif
visual=DefaultVisual(xdis, 0);
ui_setup();
screen_num = DefaultScreen(xdis);
screen_width = ui.screen_width_factor*DisplayWidth(xdis, screen_num)/100;
screen_width &= -4;
screen_height = ui.screen_height_factor*DisplayHeight(xdis, screen_num)/100;
screen_totpix=screen_width*(screen_height+1);
// *****************************************************************
// Set the variables Linrad uses to access the screen.
init_font(ui.font_scale);
if(lir_errcod != 0)goto exitmain;
xwin=XCreateSimpleWindow(xdis, RootWindow(xdis, 0), 
                                    0, 0, screen_width, screen_height, 1, 0, 0);
// We want to know about the user clicking on the close window button
wm_delete_window = XInternAtom(xdis, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(xdis,xwin, &wm_delete_window, 1);
cross_cursor = XCreateFontCursor(xdis, XC_diamond_cross);
// attach the icon cursor to our window
XDefineCursor(xdis, xwin, cross_cursor);
xgc=DefaultGC(xdis, 0);
color_depth = DefaultDepth(xdis, screen_num );
if(visual->class!=TrueColor && color_depth != 8)
  {
  printf("Unknown color type\n");
  exit(1);
  }
bitmap_pad=color_depth;  
switch (color_depth)
  {
  case 24:
  bitmap_pad=32;
  mempix_char=(unsigned char *)malloc((screen_totpix+1)*4);
  for(i=0; i<(screen_totpix+1)*4;i++)mempix_char[i]=0;
// ******************************************************************
// Rearrange the palette. It was designed for svgalib under Linux
  for(i=0; i<3*256; i++)
    {
    svga_palette[i]<<=2;
    if(svga_palette[i] != 0) svga_palette[i]|=3;
    }
  break;
  
  case 16:
  mempix_shi=(unsigned short int*)malloc((screen_totpix+1)*sizeof(unsigned short int));
  mempix_char=(void*)mempix_shi;
  for(i=0; i<screen_totpix+1; i++)mempix_shi[i]=0;
// ******************************************************************
  ipalette=(void*)(&svga_palette[0]);
  for(i=0; i<256; i++)
    {
    k=svga_palette[3*i+2];
    k&=0xfffe;
    k<<=5;
    k|=svga_palette[3*i+1];
    k&=0xfffe;
    k<<=6;
    k|=svga_palette[3*i  ];
    k>>=1;
    ipalette[i]=k;
    }
  break;
  
  case 8:
  mempix_char=(unsigned char*)malloc((screen_totpix+1)+256);
  defpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
  lirpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
  pixdiff=(float*)malloc(256*256*sizeof(float));
  xpalette=&mempix_char[screen_totpix+1];
  for(i=0; i<(screen_totpix+1)+256; i++)mempix_char[i]=0;
  lir_colormap=XCreateColormap(xdis, xwin, visual, AllocAll);
  default_colormap = DefaultColormap(xdis, screen_num);
// Store the default colormap in defpix
  for(id=0; id<256; id++)
    {
    xco.pixel=id;
    k=XQueryColor (xdis,default_colormap,&xco);  
    defpix[id].red=xco.red;
    defpix[id].green=xco.green;
    defpix[id].blue=xco.blue;
    defpix[id].flag=0;
    defpix[id].pixel=id;
    defpix[id].total=    ( (float)((unsigned int)defpix[id].red)*
                                  (unsigned int)defpix[id].red+
                          (float)((unsigned int)defpix[id].green)*
                                  (unsigned int)defpix[id].green+
                          (float)((unsigned int)defpix[id].blue)*
                                  (unsigned int)defpix[id].blue);
    }
// svga_palette uses the six lowest bits for the colour intensities.
// shift left by 10 to move our data to occupy the six highest bits.
// Store the svgalib palette.
  for(il=0; il<MAX_SVGA_PALETTE; il++)
    {
    lirpix[il].red=svga_palette[3*il+2]<<2;
    lirpix[il].green=svga_palette[3*il+1]<<2;
    lirpix[il].blue=svga_palette[3*il  ]<<2;
    if(lirpix[il].red != 0)lirpix[il].red|=3;
    if(lirpix[il].green != 0)lirpix[il].green|=3;
    if(lirpix[il].blue != 0)lirpix[il].blue|=3;
    lirpix[il].red<<=8;
    lirpix[il].green<<=8;
    lirpix[il].blue<<=8;
    lirpix[il].pixel=il;
    lirpix[il].flag=1;
    lirpix[il].total=   ( (float)((unsigned int)lirpix[il].red)*
                                  (unsigned int)lirpix[il].red+
                          (float)((unsigned int)lirpix[il].green)*
                                  (unsigned int)lirpix[il].green+
                          (float)((unsigned int)lirpix[il].blue)*
                                  (unsigned int)lirpix[il].blue);
    }
  for(il=MAX_SVGA_PALETTE; il<256; il++)
    {
    lirpix[il].red=0;
    lirpix[il].green=0;
    lirpix[il].blue=0;
    lirpix[il].pixel=il;
    lirpix[il].flag=0;
    }
#define M 0.00000001
#define N 0x100
// Sort lirpix in order of ascending total intensity.
  for(il=0; il<MAX_SVGA_PALETTE-1; il++)
    {
    t1=0;
    m=il;
    for(kl=il; kl<MAX_SVGA_PALETTE; kl++)
      {
      if(lirpix[kl].total > t1)
        {
        t1=lirpix[kl].total;
        m=kl;
        }
      }  
    tmppix=lirpix[il];
    lirpix[il]=lirpix[m];
    lirpix[m]=tmppix;
    }
// Compute the similarity between lirpix and defpix and store in a matrix.
  for(il=0; il<MAX_SVGA_PALETTE; il++)
    {
    for(id=0; id<256; id++)
      {
      t2=pow((float)(int)(((unsigned int)lirpix[il].red-
                      (unsigned int)defpix[id].red)),2.0)+
         pow((float)(int)(((unsigned int)lirpix[il].green-
                      (unsigned int)defpix[id].green)),2.0)+
         pow((float)(int)(((unsigned int)lirpix[il].blue-
                      (unsigned int)defpix[id].blue)),2.0);
      pixdiff[id+il*256]=t2;
      }
    }  
// Reorder the default colormap for the diagonal elements
// of pixdiff (up to MAX_SVGA_PALETTE-1) to become as small
// as possible when stepping in the ascending order that
// lirpix currently is sorted in.
  for(il=0; il<MAX_SVGA_PALETTE; il++)
    {
    t1=BIG;
    kd=0;
    for(id=0; id<256; id++)
      {
      if(pixdiff[id+il*256] < t1)
        {
        t1=pixdiff[id+il*256];
        kd=id;
        }
      }
    tmppix=defpix[il];
    defpix[il]=defpix[kd];
    defpix[kd]=tmppix;
    for(kl=0; kl<MAX_SVGA_PALETTE; kl++)
      {
      t1=pixdiff[kd+kl*256];
      pixdiff[kd+kl*256]=pixdiff[il+kl*256];
      pixdiff[il+kl*256]=t1;
      }
    }
  for(i=0; i<MAX_SVGA_PALETTE; i++)
    {
    xco.pixel=defpix[i].pixel;
    xco.red=lirpix[i].red;
    xco.green=lirpix[i].green;
    xco.blue=lirpix[i].blue;
    xco.flags=DoRed|DoGreen|DoBlue;
    xco.pad=0;
    k=XStoreColor(xdis, lir_colormap, &xco);  
    if(k==0)
      {
      printf("\nPalette failed\n");
      goto exitmain;
      }
    xpalette[lirpix[i].pixel]=xco.pixel;
    }
  for(i=MAX_SVGA_PALETTE; i<256; i++)
    {
    xco.pixel=defpix[i].pixel;
    xco.red=defpix[i].red;
    xco.green=defpix[i].green;
    xco.blue=defpix[i].blue;
    xco.flags=DoRed|DoGreen|DoBlue;
    xco.pad=0;
    k=XStoreColor(xdis, lir_colormap, &xco);  
    if(k==0)
      {
      printf("\nPalette failed\n");
      goto exitmain;
      }
    xpalette[i]=lirpix[i].pixel;
    }
  XSetWindowColormap(xdis, xwin, lir_colormap);
  free(defpix);
  free(lirpix);
  free(pixdiff);
  break;
  
  default:
  printf("\nUnknown color depth: %d\n",color_depth);
  goto exitmain;
  } 
if(X11_accesstype==X11_STANDARD)
  {
  ximage=XCreateImage(xdis, visual, color_depth, ZPixmap, 0, 
          (char*)(mempix_char), screen_width, screen_height, bitmap_pad, 0);
  }
#if SHM_INSTALLED == 1
else
  { 
  shminfo=(XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo));
  memset(shminfo,0, sizeof(XShmSegmentInfo));
  ximage =XShmCreateImage(xdis, visual, color_depth, ZPixmap,NULL, 
                           shminfo, screen_width, screen_height );
  shminfo->shmid=shmget(IPC_PRIVATE,
		     ximage->bytes_per_line*
		     ximage->height,IPC_CREAT|0777);
  shminfo->shmaddr = ximage->data = shmat (shminfo->shmid, 0, 0);
// replace  address in mempix_char and mempix_shi by shared memory address 
  switch (color_depth)
    {
    case 24:
    free(mempix_char);
    mempix_char=(unsigned char *)(ximage->data);
    break;
  
    case 16:
    free(mempix_char);
    mempix_char=(unsigned char *)(ximage->data);
    mempix_shi=(void *)(ximage->data);
    break;

    case 8:
    free(mempix_char);
    mempix_char=(unsigned char *)(ximage->data);
    defpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
    lirpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
    pixdiff=(float*)malloc(256*256*sizeof(float));
    xpalette=&mempix_char[screen_totpix+1];
    for(i=0; i<(screen_totpix+1)+256; i++)mempix_char[i]=0;
    lir_colormap=XCreateColormap(xdis, xwin, visual, AllocAll);
    default_colormap = DefaultColormap(xdis, screen_num);
// Store the default colormap in defpix
    for(id=0; id<256; id++)
      {
      xco.pixel=id;
      k=XQueryColor (xdis,default_colormap,&xco);  
      defpix[id].red=xco.red;
      defpix[id].green=xco.green;
      defpix[id].blue=xco.blue;
      defpix[id].flag=0;
      defpix[id].pixel=id;
      defpix[id].total=    ( (float)((unsigned int)defpix[id].red)*
                                    (unsigned int)defpix[id].red+
                            (float)((unsigned int)defpix[id].green)*
                                    (unsigned int)defpix[id].green+
                            (float)((unsigned int)defpix[id].blue)*
                                    (unsigned int)defpix[id].blue);
      } 
// svga_palette uses the six lowest bits for the colour intensities.
// shift left by 10 to move our data to occupy the six highest bits.
// Store the svgalib palette.
    for(il=0; il<MAX_SVGA_PALETTE; il++)
      {
      lirpix[il].red=svga_palette[3*il+2]<<2;
      lirpix[il].green=svga_palette[3*il+1]<<2;
      lirpix[il].blue=svga_palette[3*il  ]<<2;
      if(lirpix[il].red != 0)lirpix[il].red|=3;
      if(lirpix[il].green != 0)lirpix[il].green|=3;
      if(lirpix[il].blue != 0)lirpix[il].blue|=3;
      lirpix[il].red<<=8;
      lirpix[il].green<<=8;
      lirpix[il].blue<<=8;
      lirpix[il].pixel=il;
      lirpix[il].flag=1;
      lirpix[il].total=   ( (float)((unsigned int)lirpix[il].red)*
                                    (unsigned int)lirpix[il].red+
                            (float)((unsigned int)lirpix[il].green)*
                                    (unsigned int)lirpix[il].green+
                            (float)((unsigned int)lirpix[il].blue)*
                                    (unsigned int)lirpix[il].blue);
      }
    for(il=MAX_SVGA_PALETTE; il<256; il++)
      {
      lirpix[il].red=0;
      lirpix[il].green=0;
      lirpix[il].blue=0;
      lirpix[il].pixel=il;
      lirpix[il].flag=0;
      }
#define M 0.00000001
#define N 0x100
// Sort lirpix in order of ascending total intensity.
    for(il=0; il<MAX_SVGA_PALETTE-1; il++)
      {
      t1=0;
      m=il;
      for(kl=il; kl<MAX_SVGA_PALETTE; kl++)
        {
        if(lirpix[kl].total > t1)
          {
          t1=lirpix[kl].total;
          m=kl;
          }
        }  
      tmppix=lirpix[il];
      lirpix[il]=lirpix[m];
      lirpix[m]=tmppix;
      }
// Compute the similarity between lirpix and defpix and store in a matrix.
    for(il=0; il<MAX_SVGA_PALETTE; il++)
      {
      for(id=0; id<256; id++)
        {
        t2=pow((float)(int)(((unsigned int)lirpix[il].red-
                        (unsigned int)defpix[id].red)),2.0)+
           pow((float)(int)(((unsigned int)lirpix[il].green-
                        (unsigned int)defpix[id].green)),2.0)+
           pow((float)(int)(((unsigned int)lirpix[il].blue-
                        (unsigned int)defpix[id].blue)),2.0);
        pixdiff[id+il*256]=t2;
        }
      }  
// Reorder the default colormap for the diagonal elements
// of pixdiff (up to MAX_SVGA_PALETTE-1) to become as small
// as possible when stepping in the ascending order that
// lirpix currently is sorted in.
    for(il=0; il<MAX_SVGA_PALETTE; il++)
      {
      t1=BIG;
      kd=0;
      for(id=0; id<256; id++)
        {
        if(pixdiff[id+il*256] < t1)
          {
          t1=pixdiff[id+il*256];
          kd=id;
          }
        }
      tmppix=defpix[il];
      defpix[il]=defpix[kd];
      defpix[kd]=tmppix;
      for(kl=0; kl<MAX_SVGA_PALETTE; kl++)
        {
        t1=pixdiff[kd+kl*256];
        pixdiff[kd+kl*256]=pixdiff[il+kl*256];
        pixdiff[il+kl*256]=t1;
        }
      }
    for(i=0; i<MAX_SVGA_PALETTE; i++)
      {
      xco.pixel=defpix[i].pixel;
      xco.red=lirpix[i].red;
      xco.green=lirpix[i].green;
      xco.blue=lirpix[i].blue;
      xco.flags=DoRed|DoGreen|DoBlue;
      xco.pad=0;
      k=XStoreColor(xdis, lir_colormap, &xco);  
      if(k==0)
        {
        printf("\nPalette failed\n");
        goto exitmain;
        }
      xpalette[lirpix[i].pixel]=xco.pixel;
      }
    for(i=MAX_SVGA_PALETTE; i<256; i++)
      {
      xco.pixel=defpix[i].pixel;
      xco.red=defpix[i].red;
      xco.green=defpix[i].green;
      xco.blue=defpix[i].blue;
      xco.flags=DoRed|DoGreen|DoBlue;
      xco.pad=0;
      k=XStoreColor(xdis, lir_colormap, &xco);  
      if(k==0)
        {
        printf("\nPalette failed\n");
        goto exitmain;
        }
      xpalette[i]=lirpix[i].pixel;
      }
    XSetWindowColormap(xdis, xwin, lir_colormap);
    free(defpix);
    free(lirpix);
    free(pixdiff);
 
    break;
    }
  shminfo->readOnly = False;
  XShmAttach(xdis,shminfo);
  }
#endif
XInitImage(ximage);
XSelectInput(xdis, xwin, 
             ButtonPressMask|
             ExposureMask|
             KeyPressMask|
             KeyReleaseMask| 
             ButtonReleaseMask|
             PointerMotionMask);
XMapWindow(xdis, xwin);
// Create a thread that will close the entire process in a controlled way
// in case lirerr() is called or the ESC key is pressed.
sem_init(&sem_kill_all,0,0);
pthread_create(&thread_identifier_kill_all,NULL,(void*)thread_kill_all, NULL);
i=check_mmx();
mmx_present=i&1;
if(mmx_present != 0)simd_present=i/2; else simd_present=0;
lir_status=LIR_OK;
lir_sem_init(SEM_KEYBOARD);
process_event_flag=TRUE;
pthread_create(&thread_identifier_process_event,NULL,
                                        (void*)thread_process_event, NULL);
while(expose_event_done == FALSE)
  {
  lir_sleep(1000);
  }
lir_sem_init(SEM_MOUSE);
pthread_create(&thread_identifier_mouse,NULL, (void*)thread_mouse, NULL);
// Create a thread for the main menu.
users_open_devices();
if(kill_all_flag) goto skipmenu;
pthread_create(&thread_identifier_main_menu,NULL,
                                              (void*)thread_main_menu, NULL);
pthread_join(thread_identifier_main_menu,0);
skipmenu:;
sem_post(&sem_kill_all);
pthread_join(thread_identifier_kill_all,0);
lir_remove_mouse_thread();
pthread_join(thread_identifier_mouse,0);
show_errmsg(1);
lir_refresh_screen();
XSync(xdis,True);
process_event_flag=FALSE;
pthread_join(thread_identifier_process_event,0);
XFreeCursor(xdis, cross_cursor);
if(X11_accesstype==X11_STANDARD)
  {
  free(mempix_char);
  }
#if SHM_INSTALLED == 1
else
  { 
  XShmDetach(xdis,shminfo);
  shmdt(shminfo->shmaddr);
  shmctl(shminfo->shmid,IPC_RMID,NULL);
  free(shminfo);
  }
#endif 	
exitmain:;
users_close_devices();
lir_close_serport();
free(vga_font);
XCloseDisplay(xdis);
free(keyboard_buffer);
if(dmp!=NULL)fclose(dmp);
return lir_errcod;
}

void thread_process_event(void)
{
int chr;
int cc;
XEvent ev;
char key_buff[16];
int count, m;
KeySym ks;
int mbutton_state;
mbutton_state=0;
while(process_event_flag)
  {
  XNextEvent(xdis, &ev);
  switch(ev.type)
    {
// We want to know about the user clicking on the close window button
    case ClientMessage:
    if ( ev.xclient.data.l[0] == (int)(wm_delete_window) )
      {
      printf ( "Shutting down now!!!\n" );
      chr = X_ESC_SYM;
      sem_post(&sem_kill_all);
      store_in_kbdbuf(0);
      return;
      } 
    break;

    case Expose:
    if(X11_accesstype==X11_STANDARD)
      {
      XPutImage(xdis, xwin, xgc, ximage,0,0,0,0, screen_width, screen_height);
      }
    else
      { 
      XShmPutImage (xdis, xwin, xgc, ximage, 0, 0, 0, 0, screen_width, screen_height, FALSE);
       }
    if(color_depth==8)XInstallColormap(xdis, lir_colormap);
    expose_event_done=TRUE;
    break;

    case ButtonPress:
    if ( (ev.xbutton.button == Button1) != 0)
      {
      new_lbutton_state=1;
      goto mousepost;
      }
    if ( (ev.xbutton.button == Button3) != 0) 
      {
      new_rbutton_state=1;
      goto mousepost;
      }
    if ( (ev.xbutton.button == Button2) != 0)
      {
      mbutton_state=1;
      }
    if(mbutton_state==0)
      {  
      if ( (ev.xbutton.button == Button5) != 0)
        {
        step_rx_frequency(1);
        }
      if ( (ev.xbutton.button == Button4) != 0)
        {
        step_rx_frequency(-1);
        }
      }
    else
      {
      m=bg.wheel_stepn;
      if ( (ev.xbutton.button == Button5) != 0)
        {
        m++;
        if(m>30)m=30;
        }
      if ( (ev.xbutton.button == Button4) != 0)
        {
        m=bg.wheel_stepn;
        m--;
        if(m<-30)m=-30;
        if(genparm[AFC_ENABLE]==0 && m<0)m=0;
        }
      bg.wheel_stepn=m;
      sc[SC_SHOW_WHEEL]++;
      make_modepar_file(GRAPHTYPE_BG);
      }
    break;

    case ButtonRelease:
    if ( (ev.xbutton.button == Button1) != 0)
      {
      new_lbutton_state=0;
      goto mousepost;
      }
    if ( (ev.xbutton.button == Button3) != 0) 
      {
      new_rbutton_state=0;
      goto mousepost;
      }
    if ( (ev.xbutton.button == Button2) != 0)
      {
      mbutton_state=0;
      }
    break;

    case MotionNotify:
    new_mouse_x= ev.xbutton.x;
    if(new_mouse_x < 0)new_mouse_x=0;
    if(new_mouse_x >= screen_width)new_mouse_x=screen_width-1;
    new_mouse_y= ev.xbutton.y;
    if(new_mouse_y < 0)new_mouse_y=0;
    if(new_mouse_y >= screen_height)new_mouse_y=screen_height-1;
mousepost:;
    lir_sem_post(SEM_MOUSE);
    break;
  
    case KeyPress:
    chr = XKeycodeToKeysym(xdis, ev.xkey.keycode, 0);
    if(newcomer_escflag)
      {
      cc=toupper(chr);
      if(cc=='Y')goto escexit;
      if(cc!='N')break;
      newcomer_escpress(1);
      newcomer_escflag=FALSE;
      break;
      }
    if(chr == X_ESC_SYM)
      {
// The ESC key was pressed.
      if(ui.newcomer_mode != 0)
        {
        newcomer_escpress(0);
        newcomer_escflag=TRUE;
        break;
        }
escexit:;
      sem_post(&sem_kill_all);
      store_in_kbdbuf(0);
      return;
      }    
    if(chr == X_SHIFT_SYM_L || chr == X_SHIFT_SYM_R)
      {
      shift_key_status=1;
      break;
      }
// Get ASCII codes from Dec 32 to Dec 127
    count = XLookupString((XKeyEvent *)&ev, key_buff, 2, &ks,NULL);
    if ((count == 1) && ((int)key_buff[0]>31) )
      {
      store_in_kbdbuf((int)key_buff[0]);
      break;
      }
    cc=0;
    if(chr >= X_F1_SYM && chr <= X_F12_SYM)
      {
      if(chr <= X_F10_SYM)
        {
        if(shift_key_status == 0)
          {
          cc=F1_KEY+chr-X_F1_SYM;
          }
        else  
          {
          cc=SHIFT_F1_KEY+chr-X_F1_SYM;
          if(chr > X_F2_SYM)cc++;
          if(chr >= X_F9_SYM)cc=0;
          }
        }
      else
        {
        if(shift_key_status == 0)
          {
          cc=F11_KEY+chr-X_F11_SYM;
          }
        }  
      if(cc != 0)store_in_kbdbuf(cc);        
      break;
      }
    switch (chr)
      {
      case X_UP_SYM:
      cc=ARROW_UP_KEY;
      break;

      case X_DWN_SYM:
      cc=ARROW_DOWN_KEY;
      break;

      case X_RIGHT_SYM:
      cc=ARROW_RIGHT_KEY;
      break;

      case  X_BACKDEL_SYM:
      case X_LEFT_SYM:
      cc=ARROW_LEFT_KEY;
      break;
      
      case X_HOME_SYM:
      cc=HOME_KEY;
      break;
      
      case X_INSERT_SYM:
      cc=INSERT_KEY;
      break;
      
      case X_DELETE_SYM:
      cc=DELETE_KEY;
      break;
      
      case X_END_SYM:
      cc=END_KEY;
      break;
      
      case X_PGUP_SYM:
      cc=PAGE_UP_KEY;
      break;

      case X_PGDN_SYM:
      cc=PAGE_DOWN_KEY;
      break;
      
      case X_PAUSE_SYM:
      cc=PAUSE_KEY;
      break;
      
      case X_ENTER_SYM:
      cc=10;
      break;

      }
    if(cc != 0)store_in_kbdbuf(cc);        
    break;

    case KeyRelease:
    chr=XKeycodeToKeysym(xdis, ev.xkey.keycode, 0);
    if(chr == X_SHIFT_SYM_L || chr == X_SHIFT_SYM_R)
      {
      shift_key_status=0;
      }
    break;        
    }
  }
}

void ui_setup(void)
{
FILE *file;
int i, j, k;
int xxprint;
char s[10];
char chr;
int *uiparm;
char *parinfo;
uiparm=(int*)(&ui);
parinfo=NULL;
xxprint=investigate_cpu();
file = fopen(userint_filename, "rb");
if (file == NULL)
  {
  print_procerr(xxprint);
  printf("\n\nSetup file %s missing.",userint_filename);
full_setup:;
  for(i=0; i<MAX_UIPARM; i++) uiparm[i]=0;
  printf("\nUse W to create a new %s file after setup.\n\n",userint_filename);
  printf(
    "Press S for setup routines in normal mode or press N for NEWCOMER mode");
  printf("\nAny other key to exit. (You might want to manually edit %s)",
                                                       userint_filename);
  printf("\nThen press enter\n\n=>");
  while(fgets(s,8,stdin)==NULL);
  chr=toupper(s[0]);
  if(chr != 'S' && chr != 'N') exit(0);
  if(chr == 'N')
    {
    ui.newcomer_mode=1;
    }
  else
    {
    ui.newcomer_mode=0;
    }
  x_global_uiparms(0);
  ui.rx_input_mode=-1;
  ui.tx_dadev_no=-1;
  ui.rx_dadev_no=-1;
  uiparm_change_flag=TRUE;
  }
else
  {
  if(parinfo==NULL)
    {
    parinfo=malloc(4096);
    if(parinfo==NULL)
      {
      lirerr(1078);
      return;
      }
    }
  for(i=0; i<4096; i++) parinfo[i]=0;
  i=fread(parinfo,1,4095,file);
  fclose(file);
  file=NULL;
  if(i >= 4095)
    {
    goto go_full_setup;
    }
  k=0;
  for(i=0; i<MAX_UIPARM; i++)
    {
    while(parinfo[k]==' ' ||
          parinfo[k]== '\n' )k++;
    j=0;
    while(parinfo[k]== uiparm_text[i][j] && k<4096)
      {
      k++;
      j++;
      } 
    if(uiparm_text[i][j] != 0)goto go_full_setup;
    while(parinfo[k]!='[' && k<4096)k++;
    sscanf(&parinfo[k],"[%d]",&uiparm[i]);
    while(parinfo[k]!='\n')k++;
    }
  if( ui.font_scale < 1 || 
      ui.font_scale > 5 ||
      ui.check != UI_VERNR ||
      ui.screen_width_factor < 33 || 
      ui.screen_width_factor > 100 ||
      ui.screen_height_factor <33 || 
      ui.screen_height_factor > 100 ||
      ui.newcomer_mode <0 ||
      ui.newcomer_mode >1)
    {
go_full_setup:;
    printf("\n\nSetup file %s has errors",userint_filename);
    goto full_setup;
    }
  uiparm_change_flag=FALSE;
  free(parinfo);
  }
}
#include <pthread.h>
#include <semaphore.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include "globdef.h"
#include "thrdef.h"
#include "lconf.h"
#include "xdef.h"
#include "ldef.h"

#if SHM_INSTALLED == 1
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>

XShmSegmentInfo *shminfo;
int X11_accesstype;
#endif

pthread_t thread_identifier_process_event;
unsigned char *mempix_char;
unsigned short int *mempix_shi;
int first_mempix;
int last_mempix;
int process_event_flag;
int expose_event_done;
int shift_key_status;
int color_depth;
unsigned char *xpalette;


GC xgc;
XImage *ximage;
Display *xdis;
Window xwin;
Colormap lir_colormap;

#include <semaphore.h>
#include <pthread.h>
#include <ctype.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include "globdef.h"
#include "thrdef.h"
#include "uidef.h"
#include "screendef.h"
#include "lconf.h"
#include "xdef.h"
#include "keyboard_def.h"
#include "vernr.h"

#if SHM_INSTALLED == 1
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif 

extern GC xgc;
extern XImage *ximage;
extern Display *xdis;
extern Window xwin;
extern Colormap lir_colormap;


typedef struct {
unsigned short int red;
unsigned short int green;
unsigned short int blue;
unsigned int pixel;
short int flag;
float total;
}PIXINFO;

void lir_set_title(char *s)
{
char *window_name;
char wn[80];
XTextProperty window_title_property;
// Set the name of our window
// This is the string to be translated into a property. 
// translate the given string into an X property.
if(X11_accesstype==X11_STANDARD)
  {
  sprintf(wn,"%s %s",PROGRAM_NAME,s);
  }
else
  {
  sprintf(wn,"MIT SHM %s %s",PROGRAM_NAME,s);
  }
window_name=wn;
XStringListToTextProperty(&window_name, 1, &window_title_property);
XSetWMName(xdis, xwin, &window_title_property);
XFree(window_title_property.value);
}

void x_global_uiparms(int wn)
{
char s[80],ss[10];
int line;
line=0;
if(ui.vga_mode==0)ui.vga_mode=12;
if(ui.mouse_speed <=0 || ui.mouse_speed> 120)ui.mouse_speed=8;
if(ui.vga_mode < 10 || ui.vga_mode > 256)ui.vga_mode=10;
ui.process_priority=1;
clear_screen();
if(ui.newcomer_mode != 0)
  {
  ui.font_scale=2;
  ui.parport=0;
  ui.parport_pin=0;
  }
else
  {  
  sprintf(s,"Font scale (1 to 5):"); 
  if(wn==0)
    {
fntc:;
    printf("\n%s\n=>",s); 
    while(fgets(ss,8,stdin)==NULL);
    lir_inkey=toupper(ss[0]);
    if(lir_inkey < '1' || lir_inkey > '5')goto fntc;
    ui.font_scale=lir_inkey-'0';
    }
  else
    {
    lir_text(0,2,s);
    ui.font_scale=lir_get_integer(21,2,2,1,5);
    if(kill_all_flag) return;
    }
  sprintf(s,"Parport address (lpt1=888, none=0):"); 
parport_gtnum:;
  if(wn==0)
    {
    printf("\n%s\n=>",s); 
    while(fgets(ss,8,stdin)==NULL);
    sscanf(ss,"%d", &ui.parport);
    if(ui.parport < 0)goto parport_gtnum;
    }
  else
    {
    clear_lines(3,3);
    lir_text(0,3,s);
    ui.parport=lir_get_integer(36,3,5,0,99999);
    if(kill_all_flag) return;
    }
  if(ui.parport != 0)
    {
    sprintf (s,"Parport read pin (ACK=10):");
gtpin:;
    if(wn==0)
      {
      printf("\n%s\n=>",s); 
      while(fgets(ss,8,stdin)==NULL);
      sscanf(ss,"%d", &ui.parport_pin);
      }
    else
      {
      clear_lines(4,4);
      lir_text(0,4,s);
      ui.parport_pin=lir_get_integer(27,4,2,10,15);
      if(kill_all_flag) return;
      }
    if( ui.parport_pin ==14 ||
             ui.parport_pin > 15 ||
                ui.parport_pin < 10) goto gtpin;
    }    
  else
    {
    ui.parport_pin=0;
    }
  }  
sprintf(s,"Percentage of screen width to use(33 to 100):"); 
parport_wfac:;
if(wn==0)
  {
  printf("\n%s\n=>",s); 
  while(fgets(ss,8,stdin)==NULL);
  sscanf(ss,"%d", &ui.screen_width_factor);
  if(ui.screen_width_factor < 33 ||
     ui.screen_width_factor > 100)goto parport_wfac;
  }
else
  {
  clear_lines(5,5);
  lir_text(0,5,s);
  ui.screen_width_factor=lir_get_integer(47,5,3,33,100);
  if(kill_all_flag) return;
  }
sprintf(s,"Percentage of screen height to use (33 to 100):"); 
parport_hfac:;
if(wn==0)
  {
  printf("\n%s\n=>",s); 
  while(fgets(ss,8,stdin)==NULL);
  sscanf(ss,"%d", &ui.screen_height_factor);
  if(ui.screen_height_factor < 33 ||
     ui.screen_height_factor > 100)goto parport_hfac;
  printf("\n\nLinrad will now open another window.");
  printf("\nMinimize this window and click on the new window to continue.");
  printf(
      "\n\nDo not forget to save your parameters with 'W' in the main menu");
  fflush(NULL);
  }
else
  {
  clear_lines(6,6);
  lir_text(0,6,s);
  ui.screen_height_factor=lir_get_integer(49,6,3,33,100);
  if(kill_all_flag) return;
  if(ui.newcomer_mode != 0)
    {
    clear_screen();
    lir_text(0,4,"You are now in newcomer mode.");
    lir_text(0,6,"Press 'Y' to change to normal mode or 'N' to");
    lir_text(0,7,"stay in newcomer mode.");
ask_newco:;
    await_processed_keyboard();
    if(lir_inkey == 'N')goto stay_newco;
    if(lir_inkey != 'Y')goto ask_newco;
    ui.newcomer_mode=0;
    }
stay_newco:;
  lir_text(0,8,"Save the new parameters with W in the main menu");
  lir_text(0,9,"Then restart Linrad for changes to take effect.");
  lir_text(10,11,press_any_key);
  await_keyboard();
  }
}


void lin_global_uiparms(int wn)
{
int i;
i=wn;
}

// *********************************************************
// Graphics for X11
// *********************************************************

void lir_getpalettecolor(int j, int *r, int *g, int *b)
{
int k;
unsigned short int *ipalette;
switch (color_depth)
  {
  case 24:
  b[0]=(int)(svga_palette[3*j  ])>>2;
  g[0]=(int)(svga_palette[3*j+1])>>2;
  r[0]=(int)(svga_palette[3*j+2])>>2;
  break;

  case 16:
  ipalette=(void*)(&svga_palette[0]);
  k=ipalette[j];
  k<<=1;
  b[0]=k&0x3f;
  k>>=6;
  g[0]=k&0x3f;
  k>>=5;
  r[0]=k;
  break;

  case 8:
  b[0]=(int)(svga_palette[3*j  ]);
  g[0]=(int)(svga_palette[3*j+1]);
  r[0]=(int)(svga_palette[3*j+2]);
  break;
  }
}

void lir_fillbox(int x, int y,int w, int h, unsigned char c)
{
int i, j, k;
unsigned short int *ipalette;
k=(x+y*screen_width);
if(k<0 || k+(h-1)*screen_width+w > screen_totpix)
  {
  lirerr(1213);
  return;
  }
if(first_mempix > k)first_mempix=k;
switch (color_depth)
  {
  case 24:
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      mempix_char[4*(k+i)  ]=svga_palette[3*c  ];
      mempix_char[4*(k+i)+1]=svga_palette[3*c+1];
      mempix_char[4*(k+i)+2]=svga_palette[3*c+2];
      }
    k+=screen_width;
    }
  break;
      
  case 16:
  ipalette=(void*)(&svga_palette[0]);
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      mempix_shi[k+i]=ipalette[c];
      }
    k+=screen_width;
    }
  break;

  case 8:
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      mempix_char[k+i]=xpalette[c];
      }
    k+=screen_width;
    }
  break;
  }    
k-=screen_width-w;
if(last_mempix < k)last_mempix=k;
}

void lir_getbox(int x, int y, int w, int h, void* dp)
{
unsigned char *savmem;
int i, j, k, m;
unsigned char c,c1,c2,c3;
unsigned short int *ipalette;
k=x+y*screen_width;
savmem=(unsigned char*)dp;
m=0;
c=0;
c1=0;
c2=0;
switch (color_depth)
  {
  case 24:
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      if(svga_palette[3*c  ] == mempix_char[4*(k+i)  ] &&
         svga_palette[3*c+1] == mempix_char[4*(k+i)+1] &&
         svga_palette[3*c+2] == mempix_char[4*(k+i)+2])goto store_24;
      if(svga_palette[3*c1  ] == mempix_char[4*(k+i)  ] &&
         svga_palette[3*c1+1] == mempix_char[4*(k+i)+1] &&
         svga_palette[3*c1+2] == mempix_char[4*(k+i)+2])
        {
        c3=c;
        c=c1;
        c1=c;
        goto store_24;
        }
      if(svga_palette[3*c2  ] == mempix_char[4*(k+i)  ] &&
         svga_palette[3*c2+1] == mempix_char[4*(k+i)+1] &&
         svga_palette[3*c2+2] == mempix_char[4*(k+i)+2])
        {
        c3=c;
        c=c2;
        c1=c;
        c2=c3;
        goto store_24;
        }
      c2=c1;
      c1=c;
      while(svga_palette[3*c  ] != mempix_char[4*(k+i)  ] ||
            svga_palette[3*c+1] != mempix_char[4*(k+i)+1] ||
            svga_palette[3*c+2] != mempix_char[4*(k+i)+2])
        {
        c++;
        if(c>=MAX_SVGA_PALETTE)c=0;
        if(c==c1)
          {
          lirerr(1248);
          return;
          }
        }
store_24:;
      savmem[m]=c;
      m++;
      }
    k+=screen_width;
    }
  break;

  case 16:
  ipalette=(void*)(&svga_palette[0]);
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      if(ipalette[c] == mempix_shi[(k+i)]) goto store_16;
      if(ipalette[c1] == mempix_shi[(k+i)])
        {
        c3=c;
        c=c1;
        c1=c;
        goto store_16;
        }
      if(ipalette[c2] == mempix_shi[(k+i)])
        {
        c3=c;
        c=c2;
        c1=c;
        c2=c3;
        goto store_16;
        }
      c2=c1;
      c1=c;
      while(ipalette[c] != mempix_shi[(k+i)])
        {
        c++;
        if(c>=MAX_SVGA_PALETTE)c=0;
        if(c==c1)
          {
          lirerr(1248);
          return;
          }
        }
store_16:;
      savmem[m]=c;
      m++;
      }
    k+=screen_width;
    }
  break;

  case 8:
  for(j=0; j<h; j++)
    {
    for(i=0; i<w; i++)
      {
      if(xpalette[c] == mempix_char[(k+i)]) goto store_8;
      if(xpalette[c1] == mempix_char[(k+i)])
        {
        c3=c;
        c=c1;
        c1=c;
        goto store_8;
        }
      if(xpalette[c2] == mempix_char[(k+i)])
        {
        c3=c;
        c=c2;
        c1=c;
        c2=c3;
        goto store_8;
        }
      c2=c1;
      c1=c;
      while(xpalette[c] != mempix_char[(k+i)])
        {
        c++;
        if(c>=MAX_SVGA_PALETTE)c=0;
        if(c==c1)
          {
          lirerr(1248);
          return;
          }
        }
store_8:;
      savmem[m]=c;
      m++;
      }
    k+=screen_width;
    }
  break;
  }
}

void lir_putbox(int x, int y, int w, int h, void* dp)
{
unsigned char *savmem;
int i, j, k, m;
unsigned short int *ipalette;
k=(x+y*screen_width);
if(k<0 || k+(h-1)*screen_width+w-1 >= screen_totpix)
  {
  lirerr(1213);
  return;
  }
if(first_mempix > k)first_mempix=k;
m=0;
savmem=(unsigned char*)dp;
switch (color_depth)
  {
  case 24:
  for(j=0; j<h; j++)
    {  
    for(i=0; i<w; i++)
      {
      mempix_char[4*(k+i)  ]=svga_palette[3*savmem[m]  ];
      mempix_char[4*(k+i)+1]=svga_palette[3*savmem[m]+1];
      mempix_char[4*(k+i)+2]=svga_palette[3*savmem[m]+2];
      m++;
      }
    k+=screen_width;
    }
  break;
  
  case 16:
  ipalette=(void*)(&svga_palette[0]);
  for(j=0; j<h; j++)
    {  
    for(i=0; i<w; i++)
      {
      mempix_shi[k+i]=ipalette[savmem[m]];
      m++;
      }
    k+=screen_width;
    }
  break;

  case 8:
  for(j=0; j<h; j++)
    {  
    for(i=0; i<w; i++)
      {
      mempix_char[k+i]=xpalette[savmem[m]];
      m++;
      }
    k+=screen_width;
    }
  }  
if(last_mempix < k)last_mempix=k;
}
void lir_hline(int x1, int y, int x2, unsigned char c)
{
int i, ia, ib;
unsigned short int *ipalette;
ia=y*screen_width;
if(x1 <= x2)
  {
  ib=ia+x2;
  ia+=x1;
  }
else
  {
  ib=ia+x1;
  ia+=x2;
  }
if(ia < 0 || ib >= screen_totpix)
  {
  lirerr(1214);
  return;
  }
switch (color_depth)
  {
  case 24:
  for(i=ia; i<=ib; i++)
    {
    mempix_char[4*i  ]=svga_palette[3*c  ];
    mempix_char[4*i+1]=svga_palette[3*c+1];
    mempix_char[4*i+2]=svga_palette[3*c+2];
    }
  break;
  
  case 16:
  ipalette=(void*)(&svga_palette[0]);
  for(i=ia; i<=ib; i++)
    {
    mempix_shi[i]=ipalette[c];
    }
  break;

  case 8:
  for(i=ia; i<=ib; i++)
    {
    mempix_char[i]=xpalette[c];
    }
  break;
  }
if(first_mempix > ia)first_mempix=ia;
if(last_mempix < ib)last_mempix=ib;
}

void lir_line(int x1, int yy1, int x2,int y2, unsigned char c)
{
int ia;
int i,j,k;
int xd, yd;
float t1,t2,delt;
unsigned short int *ipalette;
if(x1 < 0)x1=0;
if(x1 >= screen_width)x1=screen_width-1;
if(x2 < 0)x2=0;
if(x2 >= screen_width)x2=screen_width-1;
if(yy1 < 0)yy1=0;
if(yy1 >= screen_height)yy1=screen_height-1;
if(y2 < 0)y2=0;
if(y2 >= screen_height)y2=screen_height-1;
xd=x2-x1;
yd=y2-yy1;
if(yd==0)
  {
  if(xd==0)
    {
    lir_setpixel(x1,yy1,c);
    }
  else
    {
    lir_hline(x1,yy1,x2,c);
    }
  return;
  }  
if(abs(xd)>=abs(yd))
  {
  if(xd>=0)
    {
    k=1;
    }
  else
    {
    k=-1;
    }  
  if(yd >= 0)
    {
    delt=0.5;
    }
  else
    {  
    delt=-0.5;
    }
  t1=yy1;
  t2=(float)(yd)/abs(xd);
  i=x1-k;
  switch (color_depth)
    {
    case 24:
    while(i!=x2)
      {
      i+=k;
      j=t1+delt;
      ia=i+j*(screen_width);
      mempix_char[4*ia  ]=svga_palette[3*c  ];
      mempix_char[4*ia+1]=svga_palette[3*c+1];
      mempix_char[4*ia+2]=svga_palette[3*c+2];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;
    
    case 16:
    ipalette=(void*)(&svga_palette[0]);
    while(i!=x2)
      {
      i+=k;
      j=t1+delt;
      ia=i+j*(screen_width);
      mempix_shi[ia  ]=ipalette[c  ];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;
    
    case 8:
    while(i!=x2)
      {
      i+=k;
      j=t1+delt;
      ia=i+j*(screen_width);
      mempix_char[ia  ]=xpalette[c  ];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;
        
    }  
  }  
else
  {
  if(yd>=0)
    {
    k=1;
    }
  else
    {
    k=-1;
    } 
  if(xd >= 0)
    {
    delt=0.5;
    }
  else
    {  
    delt=-0.5;
    }
  t1=x1;
  t2=(float)(xd)/abs(yd);
  i=yy1-k;
  switch (color_depth)
    {
    case 24:
    while(i!=y2)
      {
      i+=k;
      j=t1+delt;
      ia=j+i*(screen_width);
      mempix_char[4*ia  ]=svga_palette[3*c  ];
      mempix_char[4*ia+1]=svga_palette[3*c+1];
      mempix_char[4*ia+2]=svga_palette[3*c+2];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;
    
    case 16:
    ipalette=(void*)(&svga_palette[0]);
    while(i!=y2)
      {
      i+=k;
      j=t1+delt;
      ia=j+i*(screen_width);
      mempix_shi[ia  ]=ipalette[c  ];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;

    case 8:
    while(i!=y2)
      {
      i+=k;
      j=t1+delt;
      ia=j+i*(screen_width);
      mempix_char[ia  ]=xpalette[c  ];
      if(first_mempix > ia)first_mempix=ia;
      if(last_mempix < ia)last_mempix=ia;
      t1+=t2;
      }
    break;
    }    
  }  
}

void lir_setpixel(int x, int y, unsigned char c)
{
int ia;
unsigned short int *ipalette;
ia=x+y*screen_width;
if(ia < 0 || ia >= screen_totpix)
  {
  DEB"\nwrite: x=%d   y=%d",x,y);
  lirerr(1210);
  return;
  }
switch (color_depth)
  {
  case 24:
  mempix_char[4*ia  ]=svga_palette[3*c  ];
  mempix_char[4*ia+1]=svga_palette[3*c+1];
  mempix_char[4*ia+2]=svga_palette[3*c+2];
  break;
  
  case 16:
  ipalette=(void*)(&svga_palette[0]);
  mempix_shi[ia]=ipalette[c];
  break;

  case 8:
  mempix_char[ia]=xpalette[c];
  break;
  }
if(first_mempix > ia)first_mempix=ia;
if(last_mempix < ia)last_mempix=ia;
}

void clear_screen(void)
{
int i, k;
switch (color_depth)
  {
  case 24:
  k=4*screen_width*screen_height;
  for(i=0; i<k; i+=4)
    {
    mempix_char[i]=0;
    mempix_char[i+1]=0;
    mempix_char[i+2]=0;
    mempix_char[i+3]=255;
    }
  break;

  case 16:
  k=screen_width*screen_height;
  for(i=0; i<k; i++)
    {
    mempix_shi[i]=0;
    }
  break;
  
  case 8:
  k=screen_width*screen_height;
  for(i=0; i<k; i++)
    {
    mempix_char[i]=xpalette[0];
    }
  }
first_mempix=0;
last_mempix=screen_totpix-1;
lir_refresh_screen();
}

void lir_refresh_screen(void)
{
int l1, h, h1, n;
if(last_mempix >= first_mempix )
  {
  l1=first_mempix/screen_width;
  h=last_mempix/screen_width-l1+1;
  if(h>screen_height)h=screen_height;
  first_mempix=0x7fffffff;
  last_mempix=0;
  while(h>0)
    {
    n=(5*h)/screen_height;
    if(n > 1)
      {
      h1=h/n;
      }
    else
      {
      h1=h;
      }
    if(X11_accesstype==X11_STANDARD)
      {
      XPutImage(xdis, xwin, xgc, ximage, 0, l1, 0, l1, screen_width, h1);
      }
#if SHM_INSTALLED == 1
    else
      {
      XShmPutImage(xdis, xwin, xgc, ximage, 0, l1, 0, l1, screen_width, h1,FALSE);
      }
#endif
    l1+=h1;
    h-=h1;
    if(h > 0)lir_sched_yield();
    }
  XFlush(xdis);
  }
}

void thread_mouse(void)
{
wxmouse();
}
LINRADDARNIL