1 
2 // Copyright (c) <2012> <Leif Asbrink>
3 //
4 // Permission is hereby granted, free of charge, to any person
5 // obtaining a copy of this software and associated documentation
6 // files (the "Software"), to deal in the Software without restriction,
7 // including without limitation the rights to use, copy, modify,
8 // merge, publish, distribute, sublicense, and/or sell copies of
9 // the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
22 // OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 
25 // For help on X11 give command: "man X Interface"
26 // Event masks and event definitions are in /usr/X11R6/include/X11/X.h
27 
28 //#define UNINIT_MEMDATA 0xf7
29 #define UNINIT_MEMDATA 0
30 
31 
32 #include <string.h>
33 #include <X11/Xlib.h>
34 #include <ctype.h>
35 #include <semaphore.h>
36 #include <unistd.h>
37 #include <pthread.h>
38 #include <X11/cursorfont.h>
39 #include <X11/Xutil.h>
40 #include <signal.h>
41 #include <locale.h>
42 #include "globdef.h"
43 #include "rusage.h"
44 #include "thrdef.h"
45 #include "uidef.h"
46 #include "screendef.h"
47 #include "vernr.h"
48 #include "options.h"
49 #include "keyboard_def.h"
50 #include "lconf.h"
51 #include "xdef.h"
52 #include "ldef.h"
53 #include "conf.h"
54 
55 int w3sz_offset_hz;  //w3sz offset equal to ug.par2 to be used elsewhere in program
56 int w3sz_offset_hz_old;  //w3sz
57 int w3sz_users_flag;//w3sz
58 
59 
60 #if DO_NOT_USE_XKBLIB == TRUE
61 #define USE_XKBLIB 0
62 #else
63 #if IA64 == 0
64 #if HAVE_XKBLIB32 == 1
65 #include <X11/XKBlib.h>
66 #define USE_XKBLIB 1
67 #else
68 #define USE_XKBLIB 0
69 #endif
70 #else
71 #if HAVE_XKBLIB64 == 1
72 #include <X11/XKBlib.h>
73 #define USE_XKBLIB 1
74 #else
75 #define USE_XKBLIB 0
76 #endif
77 #endif
78 #endif
79 
80 #if SHM_INSTALLED == 1
81 #include <X11/extensions/XShm.h>
82 #include <sys/ipc.h>
83 #include <sys/shm.h>
84 extern XShmSegmentInfo *shminfo;
85 int ShmMajor,ShmMinor;
86 Bool ShmPixmaps;
87 #endif
88 
89 extern GC xgc;
90 extern XImage *ximage;
91 extern Display *xdis;
92 extern Window xwin;
93 extern Colormap lir_colormap;
94 
95 int uninit_mem_begin;
96 int newcomer_escflag;
97 
98 typedef struct {
99 unsigned short int red;
100 unsigned short int green;
101 unsigned short int blue;unsigned int pixel;
102 short int flag;
103 float total;
104 }PIXINFO;
105 
106 #define LINRAD "Linrad"
107 
108 // We want to know about the user clicking on the close window button
109 Atom wm_delete_window;
110 
111 
main(int argc,char ** argv)112 int main(int argc, char **argv)
113 {
114 int id,il,kd,kl;
115 int bitmap_pad;
116 float t1,t2;
117 PIXINFO *defpix, *lirpix;
118 float *pixdiff;
119 PIXINFO tmppix;
120 Colormap default_colormap;
121 char *hostname;
122 Visual *visual;
123 int i, k, m, screen_num;
124 Cursor cross_cursor;
125 unsigned short int *ipalette;
126 XColor xco;
127 XClassHint* classHint;
128 (void) argc;
129 setlocale(LC_ALL,"POSIX");
130 #if UNINIT_MEMDATA != 0
131   {
132   char *parinfo;
133   parinfo=(char*)(&uninit_mem_begin);
134   k=(char*)&mirics-parinfo;
135   for(i=0; i<k; i++)parinfo[i]=UNINIT_MEMDATA;
136   }
137 #endif
138 for(i=0; i<MAX_LIREVENT; i++)
139   {
140   lir_event_cond[i]=(pthread_cond_t) PTHREAD_COND_INITIALIZER;
141   }
142 XInitThreads();
143 #if SERVER == 1
144 pthread_create(&thread_identifier_html_server,NULL,
145                                            (void*)thread_html_server, NULL);
146 #endif
147 
148 #if (DUMPFILE == TRUE)
149   {
150   dmp = fopen("dmp", "w");
151   dmp1 = fopen("dmp1", "w");
152   DEB"\n******************************\n");
153   }
154 #else
155   {
156   dmp=NULL;
157   }
158 #endif
159 expose_event_done=FALSE;
160 first_mempix=0x7fffffff;
161 last_mempix=0;
162 shift_key_status=0;
163 os_flag=OS_FLAG_X;
164 init_os_independent_globals();
165 newcomer_escflag=FALSE;
166 serport=-1;
167 keyboard_buffer=malloc(KEYBOARD_BUFFER_SIZE*sizeof(int));
168 if (argv[1] == NULL)
169   {
170   hostname = NULL;
171   }
172 else
173   {
174   hostname = argv[1];
175   }
176 xdis = XOpenDisplay(hostname);
177 if (xdis == NULL)
178   {
179   fprintf(STDERR, "\nCan't open display: %s\n", hostname);
180   return(10);
181   }
182 ui_setup();
183 X11_accesstype=X11_STANDARD;
184 #if SHM_INSTALLED == 1
185 // test if the X11 server supports MIT-SHM
186 if(ui.shm_mode != 0)
187   {
188   if(XShmQueryVersion(xdis,&ShmMajor,&ShmMinor,&ShmPixmaps))
189     {
190     X11_accesstype=X11_MIT_SHM;
191     }
192   else
193     {
194     printf("\nThe parameter shm_mode in par_userint specifies MIT-SHM");
195     printf("\nbut the X11 server does not support MIT-SHM \n");
196     printf("Check your X11 configuration with the xdpyinfo command \n");
197     printf("and try to enable MIT-SHM  by adding following lines\n");
198     printf("to the /etc/X11/xorg.conf file :\n\n");
199     printf("Section ""Extensions"" \n");
200     printf("       Option ""MIT-SHM"" ""enable""  \n");
201     printf("EndSection \n\n");
202     goto shm_error;
203     }
204   }
205 #endif
206 visual=DefaultVisual(xdis, 0);
207 screen_num = DefaultScreen(xdis);
208 
209 if(ui.screen_width_factor > 0)
210   {
211   screen_width = ui.screen_width_factor*DisplayWidth(xdis, screen_num)/100;
212   screen_height = ui.screen_height_factor*DisplayHeight(xdis, screen_num)/100;
213   }
214 
215 else
216   {
217   screen_width = -ui.screen_width_factor;
218   screen_height = -ui.screen_height_factor;
219   if(screen_width > DisplayWidth(xdis, screen_num))
220     {
221     screen_width=DisplayWidth(xdis, screen_num);
222     }
223   if(screen_height > DisplayHeight(xdis, screen_num))
224     {
225     screen_height = DisplayHeight(xdis, screen_num);
226     }
227   }
228 screen_width &= -4;
229 screen_totpix=screen_width*(screen_height+1);
230 // *****************************************************************
231 // Set the variables Linrad uses to access the screen.
232 
233 
234 init_font(ui.font_scale);
235 if(lir_errcod != 0)goto exitmain;
236 xwin=XCreateSimpleWindow(xdis,
237                          RootWindow(xdis, 0),
238                          0,
239                          0,
240                          (unsigned int)screen_width,
241                          (unsigned int)screen_height,
242                          1,
243                          0,
244                          0);
245 // We want to know about the user clicking on the close window button
246 classHint=XAllocClassHint();
247 if(classHint)
248   {
249   classHint->res_name = LINRAD;
250   classHint->res_class = LINRAD;
251   XSetClassHint(xdis, xwin, classHint);
252   XFree(classHint);
253   }
254 wm_delete_window = XInternAtom(xdis, "WM_DELETE_WINDOW", 0);
255 XSetWMProtocols(xdis,xwin, &wm_delete_window, 1);
256 cross_cursor = XCreateFontCursor(xdis, XC_diamond_cross);
257 // attach the icon cursor to our window
258 XDefineCursor(xdis, xwin, cross_cursor);
259 xgc=DefaultGC(xdis, 0);
260 color_depth = DefaultDepth(xdis, screen_num );
261 if(visual->class!=TrueColor && color_depth != 8)
262   {
263   printf("Unknown color type\n");
264   exit(1);
265   }
266 bitmap_pad=color_depth;
267 switch (color_depth)
268   {
269   case 24:
270   bitmap_pad=32;
271   mempix_char=(unsigned char*)malloc((size_t)(screen_totpix+1)*4);
272   for(i=0; i<(screen_totpix+1)*4;i++)mempix_char[i]=0;
273 // ******************************************************************
274 // Rearrange the palette. It was designed for svgalib under Linux
275   for(i=0; i<3*256; i++)
276     {
277     svga_palette[i]=(unsigned char)(svga_palette[i]<<2);
278     if(svga_palette[i] != 0) svga_palette[i]|=3;
279     }
280   break;
281 
282   case 16:
283   mempix_shi=(unsigned short int*)malloc((size_t)(screen_totpix+1)*sizeof(unsigned short int));
284   mempix_char=(unsigned char*)mempix_shi;
285   for(i=0; i<screen_totpix+1; i++)mempix_shi[i]=0;
286 // ******************************************************************
287   ipalette=(unsigned short int*)(&svga_palette[0]);
288   for(i=0; i<256; i++)
289     {
290     k=svga_palette[3*i+2];
291     k&=0xfffe;
292     k<<=5;
293     k|=svga_palette[3*i+1];
294     k&=0xfffe;
295     k<<=6;
296     k|=svga_palette[3*i  ];
297     k>>=1;
298     ipalette[i]=(short unsigned int)k;
299     }
300   break;
301 
302   case 8:
303   mempix_char=(unsigned char*)malloc((size_t)(screen_totpix+1)+256);
304   defpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
305   lirpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
306   pixdiff=(float*)malloc(256*256*sizeof(float));
307   xpalette=&mempix_char[screen_totpix+1];
308   for(i=0; i<(screen_totpix+1)+256; i++)mempix_char[i]=0;
309   lir_colormap=XCreateColormap(xdis, xwin, visual, AllocAll);
310   default_colormap = DefaultColormap(xdis, screen_num);
311 // Store the default colormap in defpix
312   for(id=0; id<256; id++)
313     {
314     xco.pixel=(long unsigned int)id;
315     k=XQueryColor (xdis,default_colormap,&xco);
316     defpix[id].red=xco.red;
317     defpix[id].green=xco.green;
318     defpix[id].blue=xco.blue;
319     defpix[id].flag=0;
320     defpix[id].pixel=(unsigned int)id;
321     defpix[id].total=(float)defpix[id].red*(float)defpix[id].red+
322                      (float)defpix[id].green*(float)defpix[id].green+
323                      (float)defpix[id].blue*(float)defpix[id].blue;
324     }
325 // svga_palette uses the six lowest bits for the colour intensities.
326 // shift left by 10 to move our data to occupy the six highest bits.
327 // Store the svgalib palette.
328   for(il=0; il<MAX_SVGA_PALETTE; il++)
329     {
330     lirpix[il].red=(short unsigned int)(svga_palette[3*il+2]<<2);
331     lirpix[il].green=(short unsigned int)(svga_palette[3*il+1]<<2);
332     lirpix[il].blue=(short unsigned int)(svga_palette[3*il  ]<<2);
333     if(lirpix[il].red != 0)lirpix[il].red|=3;
334     if(lirpix[il].green != 0)lirpix[il].green|=3;
335     if(lirpix[il].blue != 0)lirpix[il].blue|=3;
336     lirpix[il].red=(short unsigned int)(lirpix[il].red<<8);
337     lirpix[il].green=(short unsigned int)(lirpix[il].green<<8);
338     lirpix[il].blue=(short unsigned int)(lirpix[il].blue<<8);
339     lirpix[il].pixel=(unsigned int)il;
340     lirpix[il].flag=1;
341     lirpix[il].total=(float)lirpix[il].red*(float)lirpix[il].red+
342                      (float)lirpix[il].green*(float)lirpix[il].green+
343                      (float)lirpix[il].blue*(float)lirpix[il].blue;
344     }
345   for(il=MAX_SVGA_PALETTE; il<256; il++)
346     {
347     lirpix[il].red=0;
348     lirpix[il].green=0;
349     lirpix[il].blue=0;
350     lirpix[il].pixel=(unsigned int)il;
351     lirpix[il].flag=0;
352     }
353 #define M 0.00000001
354 #define N 0x100
355 // Sort lirpix in order of ascending total intensity.
356   for(il=0; il<MAX_SVGA_PALETTE-1; il++)
357     {
358     t1=0;
359     m=il;
360     for(kl=il; kl<MAX_SVGA_PALETTE; kl++)
361       {
362       if(lirpix[kl].total > t1)
363         {
364         t1=lirpix[kl].total;
365         m=kl;
366         }
367       }
368     tmppix=lirpix[il];
369     lirpix[il]=lirpix[m];
370     lirpix[m]=tmppix;
371     }
372 // Compute the similarity between lirpix and defpix and store in a matrix.
373   for(il=0; il<MAX_SVGA_PALETTE; il++)
374     {
375     for(id=0; id<256; id++)
376       {
377       t2=(float)(pow((float)(lirpix[il].red-defpix[id].red),2.0)+
378                  pow((float)(lirpix[il].green-defpix[id].green),2.0)+
379                  pow((float)(lirpix[il].blue-defpix[id].blue),2.0));
380       pixdiff[id+il*256]=t2;
381       }
382     }
383 // Reorder the default colormap for the diagonal elements
384 // of pixdiff (up to MAX_SVGA_PALETTE-1) to become as small
385 // as possible when stepping in the ascending order that
386 // lirpix currently is sorted in.
387   for(il=0; il<MAX_SVGA_PALETTE; il++)
388     {
389     t1=(float)BIG;
390     kd=0;
391     for(id=0; id<256; id++)
392       {
393       if(pixdiff[id+il*256] < t1)
394         {
395         t1=pixdiff[id+il*256];
396         kd=id;
397         }
398       }
399     tmppix=defpix[il];
400     defpix[il]=defpix[kd];
401     defpix[kd]=tmppix;
402     for(kl=0; kl<MAX_SVGA_PALETTE; kl++)
403       {
404       t1=pixdiff[kd+kl*256];
405       pixdiff[kd+kl*256]=pixdiff[il+kl*256];
406       pixdiff[il+kl*256]=t1;
407       }
408     }
409   for(i=0; i<MAX_SVGA_PALETTE; i++)
410     {
411     xco.pixel=defpix[i].pixel;
412     xco.red=lirpix[i].red;
413     xco.green=lirpix[i].green;
414     xco.blue=lirpix[i].blue;
415     xco.flags=DoRed|DoGreen|DoBlue;
416     xco.pad=0;
417     k=XStoreColor(xdis, lir_colormap, &xco);
418     if(k==0)
419       {
420       printf("\nPalette failed\n");
421       goto exitmain;
422       }
423     xpalette[lirpix[i].pixel]=(unsigned char)xco.pixel;
424     }
425   for(i=MAX_SVGA_PALETTE; i<256; i++)
426     {
427     xco.pixel=defpix[i].pixel;
428     xco.red=defpix[i].red;
429     xco.green=defpix[i].green;
430     xco.blue=defpix[i].blue;
431     xco.flags=DoRed|DoGreen|DoBlue;
432     xco.pad=0;
433     k=XStoreColor(xdis, lir_colormap, &xco);
434     if(k==0)
435       {
436       printf("\nPalette failed\n");
437       goto exitmain;
438       }
439     xpalette[i]=(unsigned char)lirpix[i].pixel;
440     }
441   XSetWindowColormap(xdis, xwin, lir_colormap);
442   free(defpix);
443   free(lirpix);
444   free(pixdiff);
445   break;
446 
447   default:
448   printf("\nUnknown color depth: %d\n",color_depth);
449   goto exitmain;
450   }
451 if(X11_accesstype==X11_STANDARD)
452   {
453   ximage=XCreateImage(xdis, visual,
454           (unsigned int)color_depth,
455           ZPixmap,
456           0,
457           (char*)(mempix_char),
458           (unsigned int)screen_width,
459           (unsigned int)screen_height+1, bitmap_pad, 0);
460   }
461 #if SHM_INSTALLED == 1
462 else
463   {
464   shminfo=(XShmSegmentInfo *)malloc(sizeof(XShmSegmentInfo));
465   memset(shminfo,0, sizeof(XShmSegmentInfo));
466   ximage =XShmCreateImage(xdis,
467                           visual,
468                           (unsigned int)color_depth,
469                           ZPixmap,
470                           NULL,
471                           shminfo,
472                           (unsigned int)screen_width,
473                           (unsigned int)screen_height+1 );
474   shminfo->shmid=shmget(IPC_PRIVATE,
475 		        (size_t)(ximage->bytes_per_line*ximage->height),
476 		        IPC_CREAT|0777);
477   shminfo->shmaddr = ximage->data = shmat (shminfo->shmid, 0, 0);
478 // replace  address in mempix_char and mempix_shi by shared memory address
479   switch (color_depth)
480     {
481     case 24:
482     free(mempix_char);
483     mempix_char=(unsigned char*)(ximage->data);
484     break;
485 
486     case 16:
487     free(mempix_char);
488     mempix_char=(unsigned char*)(ximage->data);
489     mempix_shi=(unsigned short int*)(ximage->data);
490     break;
491 
492     case 8:
493     free(mempix_char);
494     mempix_char=(unsigned char *)(ximage->data);
495     defpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
496     lirpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
497     pixdiff=(float*)malloc(256*256*sizeof(float));
498     xpalette=&mempix_char[screen_totpix+1];
499     for(i=0; i<(screen_totpix+1)+256; i++)mempix_char[i]=0;
500     lir_colormap=XCreateColormap(xdis, xwin, visual, AllocAll);
501     default_colormap = DefaultColormap(xdis, screen_num);
502 // Store the default colormap in defpix
503     for(id=0; id<256; id++)
504       {
505       xco.pixel=(long unsigned int)id;
506       k=XQueryColor (xdis,default_colormap,&xco);
507       defpix[id].red=xco.red;
508       defpix[id].green=xco.green;
509       defpix[id].blue=xco.blue;
510       defpix[id].flag=0;
511       defpix[id].pixel=(unsigned int)id;
512       defpix[id].total=(float)(defpix[id].red)*(float)defpix[id].red+
513                        (float)(defpix[id].green)*(float)defpix[id].green+
514                        (float)(defpix[id].blue)*(float)defpix[id].blue;
515       }
516 // svga_palette uses the six lowest bits for the colour intensities.
517 // shift left by 10 to move our data to occupy the six highest bits.
518 // Store the svgalib palette.
519     for(il=0; il<MAX_SVGA_PALETTE; il++)
520       {
521       lirpix[il].red=(short unsigned int)(svga_palette[3*il+2]<<2);
522       lirpix[il].green=(short unsigned int)(svga_palette[3*il+1]<<2);
523       lirpix[il].blue=(short unsigned int)(svga_palette[3*il  ]<<2);
524       if(lirpix[il].red != 0)lirpix[il].red|=3;
525       if(lirpix[il].green != 0)lirpix[il].green|=3;
526       if(lirpix[il].blue != 0)lirpix[il].blue|=3;
527       lirpix[il].red=(short unsigned int)(lirpix[il].red<<8);
528       lirpix[il].green=(short unsigned int)(lirpix[il].green<<8);
529       lirpix[il].blue=(short unsigned int)(lirpix[il].blue<<8);
530       lirpix[il].pixel=(unsigned int)il;
531       lirpix[il].flag=1;
532       lirpix[il].total= (float)(lirpix[il].red)*(float)lirpix[il].red+
533                         (float)(lirpix[il].green)*(float)lirpix[il].green+
534                         (float)(lirpix[il].blue)*(float)lirpix[il].blue;
535       }
536     for(il=MAX_SVGA_PALETTE; il<256; il++)
537       {
538       lirpix[il].red=0;
539       lirpix[il].green=0;
540       lirpix[il].blue=0;
541       lirpix[il].pixel=(unsigned int)il;
542       lirpix[il].flag=0;
543       }
544 #define M 0.00000001
545 #define N 0x100
546 // Sort lirpix in order of ascending total intensity.
547     for(il=0; il<MAX_SVGA_PALETTE-1; il++)
548       {
549       t1=0;
550       m=il;
551       for(kl=il; kl<MAX_SVGA_PALETTE; kl++)
552         {
553         if(lirpix[kl].total > t1)
554           {
555           t1=lirpix[kl].total;
556           m=kl;
557           }
558         }
559       tmppix=lirpix[il];
560       lirpix[il]=lirpix[m];
561       lirpix[m]=tmppix;
562       }
563 // Compute the similarity between lirpix and defpix and store in a matrix.
564     for(il=0; il<MAX_SVGA_PALETTE; il++)
565       {
566       for(id=0; id<256; id++)
567         {
568         t2=(float)(pow((double)(lirpix[il].red-defpix[id].red),2.0)+
569                    pow((double)((lirpix[il].green-defpix[id].green)),2.0)+
570                    pow((double)((lirpix[il].blue-defpix[id].blue)),2.0));
571         pixdiff[id+il*256]=t2;
572         }
573       }
574 // Reorder the default colormap for the diagonal elements
575 // of pixdiff (up to MAX_SVGA_PALETTE-1) to become as small
576 // as possible when stepping in the ascending order that
577 // lirpix currently is sorted in.
578     for(il=0; il<MAX_SVGA_PALETTE; il++)
579       {
580       t1=(float)BIG;
581       kd=0;
582       for(id=0; id<256; id++)
583         {
584         if(pixdiff[id+il*256] < t1)
585           {
586           t1=pixdiff[id+il*256];
587           kd=id;
588           }
589         }
590       tmppix=defpix[il];
591       defpix[il]=defpix[kd];
592       defpix[kd]=tmppix;
593       for(kl=0; kl<MAX_SVGA_PALETTE; kl++)
594         {
595         t1=pixdiff[kd+kl*256];
596         pixdiff[kd+kl*256]=pixdiff[il+kl*256];
597         pixdiff[il+kl*256]=t1;
598         }
599       }
600     for(i=0; i<MAX_SVGA_PALETTE; i++)
601       {
602       xco.pixel=defpix[i].pixel;
603       xco.red=lirpix[i].red;
604       xco.green=lirpix[i].green;
605       xco.blue=lirpix[i].blue;
606       xco.flags=DoRed|DoGreen|DoBlue;
607       xco.pad=0;
608       k=XStoreColor(xdis, lir_colormap, &xco);
609       if(k==0)
610         {
611         printf("\nPalette failed\n");
612         goto exitmain;
613         }
614       xpalette[lirpix[i].pixel]=(unsigned char)xco.pixel;
615       }
616     for(i=MAX_SVGA_PALETTE; i<256; i++)
617       {
618       xco.pixel=defpix[i].pixel;
619       xco.red=defpix[i].red;
620       xco.green=defpix[i].green;
621       xco.blue=defpix[i].blue;
622       xco.flags=DoRed|DoGreen|DoBlue;
623       xco.pad=0;
624       k=XStoreColor(xdis, lir_colormap, &xco);
625       if(k==0)
626         {
627         printf("\nPalette failed\n");
628         goto exitmain;
629         }
630       xpalette[i]=(unsigned char)lirpix[i].pixel;
631       }
632     XSetWindowColormap(xdis, xwin, lir_colormap);
633     free(defpix);
634     free(lirpix);
635     free(pixdiff);
636 
637     break;
638     }
639   shminfo->readOnly = False;
640   XShmAttach(xdis,shminfo);
641   }
642 #endif
643 XInitImage(ximage);
644 XSelectInput(xdis, xwin,
645              ButtonPressMask|
646              ExposureMask|
647              KeyPressMask|
648              KeyReleaseMask|
649              ButtonReleaseMask|
650              PointerMotionMask|
651              StructureNotifyMask);
652 XMapWindow(xdis, xwin);
653 // Create a thread that will close the entire process in a controlled way
654 // in case lirerr() is called or the ESC key is pressed.
655 lir_init_event(EVENT_KILL_ALL);
656 pthread_create(&thread_identifier_kill_all,NULL,(void*)thread_kill_all, NULL);
657 lir_init_event(EVENT_REFRESH_SCREEN);
658 pthread_create(&thread_identifier_refresh_screen,NULL,
659                                           (void*)thread_refresh_screen, NULL);
660 lir_status=LIR_OK;
661 lir_init_event(EVENT_KEYBOARD);
662 process_event_flag=TRUE;
663 pthread_create(&thread_identifier_process_event,NULL,
664                                         (void*)thread_process_event, NULL);
665 while(expose_event_done == FALSE)
666   {
667   lir_sleep(1000);
668   }
669 lir_init_event(EVENT_MOUSE);
670 pthread_create(&thread_identifier_mouse,NULL, (void*)thread_mouse, NULL);
671 // Create a thread for the main menu.
672 lir_init_event(EVENT_MANAGE_EXTIO);
673 users_open_devices();
674 if(kill_all_flag) goto skipmenu;
675 pthread_create(&thread_identifier_main_menu,NULL,
676                                               (void*)thread_main_menu, NULL);
677 while(extio_command_flag != EXTIO_COMMAND_KILL_ALL)
678   {
679   lir_await_event(EVENT_MANAGE_EXTIO);
680   switch(extio_command_flag)
681     {
682     case EXTIO_COMMAND_LOAD_DLL:
683     extio_error=load_extio_library();
684     break;
685 
686     case EXTIO_COMMAND_UNLOAD_DLL:
687     unload_extio_library();
688     break;
689 
690     case EXTIO_COMMAND_START:
691     start_extio();
692     break;
693 
694     case EXTIO_COMMAND_STOP:
695     stop_extio();
696     break;
697 
698     case EXTIO_COMMAND_KILL_ALL:
699     goto kill;
700     }
701   extio_command_flag=EXTIO_COMMAND_DONE;
702   }
703 kill:;
704 pthread_join(thread_identifier_main_menu,0);
705 skipmenu:;
706 refresh_screen_flag=FALSE;
707 lir_refresh_screen();
708 pthread_join(thread_identifier_refresh_screen,0);
709 lir_set_event(EVENT_KILL_ALL);
710 pthread_join(thread_identifier_kill_all,0);
711 lir_remove_mouse_thread();
712 pthread_join(thread_identifier_mouse,0);
713 //XSync(xdis,True);    ööööööö does never return in Ubuntu 11.04
714 pthread_kill(thread_identifier_process_event, 9);
715 process_event_flag=FALSE;
716 pthread_join(thread_identifier_process_event,0);
717 XFreeCursor(xdis, cross_cursor);
718 if(X11_accesstype==X11_STANDARD)
719   {
720   free(mempix_char);
721   }
722 #if SHM_INSTALLED == 1
723 else
724   {
725   XShmDetach(xdis,shminfo);
726   shmdt(shminfo->shmaddr);
727   shmctl(shminfo->shmid,IPC_RMID,NULL);
728   free(shminfo);
729   }
730 #endif
731 exitmain:;
732 users_close_devices();
733 lir_close_serport();
734 free(vga_font);
735 #if SHM_INSTALLED == 1
736 shm_error:;
737 #endif
738 XCloseDisplay(xdis);
739 free(keyboard_buffer);
740 if(dmp!=NULL)fclose(dmp);
741 if(dmp1!=NULL)fclose(dmp1);
742 #if SERVER == 1
743 pthread_join(thread_identifier_html_server,0);
744 #endif
745 return lir_errcod;
746 }
747 
thread_process_event(void)748 void thread_process_event(void)
749 {
750 int i, k, chr;
751 int cc, mx, my;
752 XEvent ev;
753 char key_buff[16];
754 int count, m;
755 KeySym ks;
756 int mbutton_state;
757 mbutton_state=0;
758 expose_time=current_time();
759 while(process_event_flag)
760   {
761   XNextEvent(xdis, &ev);
762   switch(ev.type)
763     {
764 // We want to know about the user clicking on the close window button
765     case ClientMessage:
766     if ( ev.xclient.data.l[0] == (int)(wm_delete_window) )
767       {
768       printf ( "Shutting down now!!!\n" );
769       chr = X_ESC_SYM;
770       lir_set_event(EVENT_KILL_ALL);
771       store_in_kbdbuf(0);
772       return;
773       }
774     break;
775 
776     case Expose:
777     expose_time=recent_time;
778     if (ev.xexpose.count == 256)
779       {
780       if( thread_status_flag[THREAD_SCREEN] == THRFLAG_ACTIVE)goto expo;
781       }
782     if (ev.xexpose.count != 0)break;
783     if( thread_status_flag[THREAD_SCREEN] != THRFLAG_SEM_WAIT &&
784         thread_status_flag[THREAD_SCREEN] != THRFLAG_ACTIVE &&
785         thread_status_flag[THREAD_SCREEN] != THRFLAG_IDLE)
786       {
787 expo:;
788       if(X11_accesstype==X11_STANDARD)
789         {
790         XPutImage(xdis, xwin, xgc, ximage,0,0,0,0,
791                 (unsigned int)screen_width, (unsigned int)screen_height);
792         }
793 #if SHM_INSTALLED == 1
794       else
795         {
796         XShmPutImage (xdis, xwin, xgc, ximage, 0, 0, 0, 0,
797           (unsigned int)screen_width, (unsigned int)screen_height, FALSE);
798         }
799 #endif
800       }
801     if(color_depth==8)XInstallColormap(xdis, lir_colormap);
802     expose_event_done=TRUE;
803     break;
804 
805     case ButtonPress:
806     if ( (ev.xbutton.button == Button1) != 0)
807       {
808       new_lbutton_state=1;
809       goto mousepost;
810       }
811     if ( (ev.xbutton.button == Button3) != 0)
812       {
813       new_rbutton_state=1;
814       goto mousepost;
815       }
816     if ( (ev.xbutton.button == Button2) != 0)
817       {
818       mbutton_state=1;
819       }
820     if(mbutton_state==0)
821       {
822       if ( (ev.xbutton.button == Button5) != 0)
823         {
824         step_rx_frequency(1);
825         }
826       if ( (ev.xbutton.button == Button4) != 0)
827         {
828         step_rx_frequency(-1);
829         }
830       }
831     else
832       {
833       m=bg.wheel_stepn;
834       if ( (ev.xbutton.button == Button5) != 0)
835         {
836         m++;
837         if(m>30)m=30;
838         }
839       if ( (ev.xbutton.button == Button4) != 0)
840         {
841         m=bg.wheel_stepn;
842         m--;
843         if(m<-30)m=-30;
844         if(genparm[AFC_ENABLE]==0 && m<0)m=0;
845         }
846       bg.wheel_stepn=m;
847       sc[SC_SHOW_WHEEL]++;
848       make_modepar_file(GRAPHTYPE_BG);
849       }
850     break;
851 
852     case ButtonRelease:
853     if ( (ev.xbutton.button == Button1) != 0)
854       {
855       new_lbutton_state=0;
856       goto mousepost;
857       }
858     if ( (ev.xbutton.button == Button3) != 0)
859       {
860       new_rbutton_state=0;
861       goto mousepost;
862       }
863     if ( (ev.xbutton.button == Button2) != 0)
864       {
865       mbutton_state=0;
866       }
867     break;
868 
869     case MotionNotify:
870     mx=new_mouse_x;
871     my=new_mouse_y;
872     new_mouse_x= ev.xbutton.x;
873     if(new_mouse_x < 0)new_mouse_x=0;
874     if(new_mouse_x >= screen_width)new_mouse_x=screen_width-1;
875     new_mouse_y= ev.xbutton.y;
876     if(new_mouse_y < 0)new_mouse_y=0;
877     if(new_mouse_y >= screen_height)new_mouse_y=screen_height-1;
878     if(  mx == new_mouse_x &&   my==new_mouse_y)break;
879     if( (mx == new_mouse_x && new_mouse_x == screen_width-1) ||
880         (my == new_mouse_y && new_mouse_y == screen_height-1)||
881         (mx == new_mouse_x && new_mouse_x == 0) ||
882         (my == new_mouse_y && new_mouse_y == 0) )break;
883 mousepost:;
884     lir_set_event(EVENT_MOUSE);
885     break;
886 
887     case KeyPress:
888 #if USE_XKBLIB == 1
889     chr=(int)XkbKeycodeToKeysym(xdis, (KeyCode)ev.xkey.keycode, 0, 0);
890 #else
891     chr=(int)XKeycodeToKeysym(xdis, (KeyCode)ev.xkey.keycode, 0);
892 #endif
893     if(newcomer_escflag == TRUE)
894       {
895       cc=toupper(chr);
896       if(cc=='Y')goto escexit;
897       if(cc!='N')break;
898       newcomer_escpress(1);
899       newcomer_escflag=FALSE;
900       break;
901       }
902     if(chr == X_ESC_SYM)
903       {
904 // The ESC key was pressed.
905       if(ui.operator_skil == OPERATOR_SKIL_NEWCOMER)
906         {
907         newcomer_escpress(0);
908         newcomer_escflag=TRUE;
909         break;
910         }
911 escexit:;
912       lir_set_event(EVENT_KILL_ALL);
913 check_threads:;
914       k=0;
915       for(i=0; i<THREAD_MAX; i++)
916         {
917         if(i != THREAD_SYSCALL &&
918            thread_command_flag[i] != THRFLAG_NOT_ACTIVE &&
919            thread_waitsem[i] == -2)
920           {
921           k++;
922           }
923         }
924       if(k != 0)
925         {
926         lir_sleep(30000);
927         goto check_threads;
928         }
929       store_in_kbdbuf(0);
930       return;
931       }
932     if(chr == X_SHIFT_SYM_L || chr == X_SHIFT_SYM_R)
933       {
934       shift_key_status=1;
935       break;
936       }
937 // Get ASCII codes from Dec 32 to Dec 127~
938     count = XLookupString((XKeyEvent *)&ev, key_buff, 2, &ks,NULL);
939     if ((count == 1) && ((int)key_buff[0]>31) )
940       {
941       store_in_kbdbuf((int)key_buff[0]);
942       break;
943       }
944     cc=0;
945     if(chr == X_NUM_ENTER_SYM)
946       {
947       store_in_kbdbuf(10);
948       break;
949       }
950     if(chr >= X_F1_SYM && chr <= X_F12_SYM)
951       {
952       if(chr <= X_F10_SYM)
953         {
954         if(shift_key_status == 0)
955           {
956           cc=F1_KEY+chr-X_F1_SYM;
957           }
958         else
959           {
960           cc=SHIFT_F1_KEY+chr-X_F1_SYM;
961           if(chr > X_F2_SYM)cc++;
962           if(chr >= X_F9_SYM)cc=0;
963           }
964         }
965       else
966         {
967         if(shift_key_status == 0)
968           {
969           cc=F11_KEY+chr-X_F11_SYM;
970           }
971         }
972       if(cc != 0)store_in_kbdbuf(cc);
973       break;
974       }
975     switch (chr)
976       {
977       case X_UP_SYM:
978       cc=ARROW_UP_KEY;
979       break;
980 
981       case X_DWN_SYM:
982       cc=ARROW_DOWN_KEY;
983       break;
984 
985       case X_RIGHT_SYM:
986       cc=ARROW_RIGHT_KEY;
987       break;
988 
989       case  X_BACKDEL_SYM:
990       case X_LEFT_SYM:
991       cc=ARROW_LEFT_KEY;
992       break;
993 
994       case X_HOME_SYM:
995       cc=HOME_KEY;
996       break;
997 
998       case X_INSERT_SYM:
999       cc=INSERT_KEY;
1000       break;
1001 
1002       case X_DELETE_SYM:
1003       cc=DELETE_KEY;
1004       break;
1005 
1006       case X_END_SYM:
1007       cc=END_KEY;
1008       break;
1009 
1010       case X_PGUP_SYM:
1011       cc=PAGE_UP_KEY;
1012       break;
1013 
1014       case X_PGDN_SYM:
1015       cc=PAGE_DOWN_KEY;
1016       break;
1017 
1018       case X_PAUSE_SYM:
1019       cc=PAUSE_KEY;
1020       break;
1021 
1022       case X_ENTER_SYM:
1023       cc=10;
1024       break;
1025 
1026       }
1027     if(cc != 0)store_in_kbdbuf(cc);
1028     break;
1029 
1030     case KeyRelease:
1031 #if USE_XKBLIB == 1
1032     chr=(int)XkbKeycodeToKeysym(xdis, (KeyCode)ev.xkey.keycode, 0, 0);
1033 #else
1034     chr=(int)XKeycodeToKeysym(xdis, (KeyCode)ev.xkey.keycode, 0);
1035 #endif
1036     if(chr == X_SHIFT_SYM_L || chr == X_SHIFT_SYM_R)
1037       {
1038       shift_key_status=0;
1039       }
1040     break;
1041 
1042     case ConfigureNotify:
1043     if(ev.xconfigure.width != screen_width ||
1044        ev.xconfigure.height != screen_height)
1045       {
1046       fprintf( stderr,"\n\nSCREEN SIZE ERROR");
1047       fprintf( stderr,
1048       "\nRestart Linrad and set the size you want with S=Global parms set up.");
1049       fprintf( stderr,
1050       "\nThis version of Linrad does not support resized windows.");
1051       }
1052       break;
1053     }
1054   }
1055 }
1056 
ui_setup(void)1057 void ui_setup(void)
1058 {
1059 size_t bytes;
1060 FILE *file;
1061 int i, j, k;
1062 int xxprint;
1063 char s[10];
1064 char chr;
1065 int *uiparm;
1066 char *parinfo;
1067 uiparm=(int*)(&ui);
1068 parinfo=NULL;
1069 #if DARWIN == 0
1070 xxprint=investigate_cpu();
1071 #else
1072 xxprint=0;
1073 simd_present=0;
1074 mmx_present=0;
1075 no_of_processors=1;
1076 #endif
1077 file = fopen(userint_filename, "rb");
1078 if (file == NULL)
1079   {
1080   printf("\n\nWELCOME TO LINRAD");
1081   printf("\nThis message is not an error, but an indication that setup");
1082   printf("\nhas not yet been done.");
1083   print_procerr(xxprint);
1084   printf("\n\nSetup file %s missing.",userint_filename);
1085 full_setup:;
1086   for(i=0; i<MAX_UIPARM; i++) uiparm[i]=0;
1087   welcome_msg();
1088   while(fgets(s,8,stdin)==NULL);
1089   chr=toupper((int)s[0]);
1090   if(chr != 'S' && chr != 'N' && chr != 'E') exit(0);
1091   if(chr == 'N')
1092     {
1093     ui.operator_skil=OPERATOR_SKIL_NEWCOMER;
1094     }
1095   else
1096     {
1097     if(chr == 'S')
1098       {
1099       ui.operator_skil=OPERATOR_SKIL_NORMAL;
1100       }
1101     else
1102       {
1103       ui.operator_skil=OPERATOR_SKIL_EXPERT;
1104       }
1105     }
1106   x_global_uiparms(0);
1107   ui.rx_input_mode=-1;
1108   ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
1109   ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
1110   ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
1111   ui.max_dma_rate=DEFAULT_MAX_DMA_RATE;
1112   ui.min_dma_rate=DEFAULT_MIN_DMA_RATE;
1113   ui.soundcard_radio=SOUNDCARD_RADIO_UNDEFINED;
1114   ui.converter_mhz=0;
1115   ui.converter_hz=0;
1116   uiparm_change_flag=TRUE;
1117   }
1118 else
1119   {
1120   if(parinfo==NULL)
1121     {
1122     parinfo=malloc(4096);
1123     if(parinfo==NULL)
1124       {
1125       fclose(file);
1126       lirerr(1078);
1127       return;
1128       }
1129     }
1130   for(i=0; i<4096; i++) parinfo[i]=0;
1131   bytes=fread(parinfo,1,4095,file);
1132   fclose(file);
1133   file=NULL;
1134   if(bytes >= 4095)
1135     {
1136     goto go_full_setup;
1137     }
1138   k=0;
1139   for(i=0; i<MAX_UIPARM; i++)
1140     {
1141     while(parinfo[k]==' ' ||
1142           parinfo[k]== '\n' )k++;
1143     j=0;
1144     while(parinfo[k]== uiparm_text[i][j] && k<4096)
1145       {
1146       k++;
1147       j++;
1148       }
1149     if(uiparm_text[i][j] != 0)goto go_full_setup;
1150     while(parinfo[k]!='[' && k<4096)k++;
1151     sscanf(&parinfo[k],"[%d]",&uiparm[i]);
1152     while(parinfo[k]!='\n')k++;
1153     }
1154   if(ui.screen_width_factor*ui.screen_height_factor <=0)goto go_full_setup;
1155   if(ui.screen_width_factor > 0)
1156     {
1157     if(ui.screen_width_factor < 25 ||
1158       ui.screen_width_factor > 100 ||
1159       ui.screen_height_factor <25 ||
1160       ui.screen_height_factor > 100)goto go_full_setup;
1161     }
1162   else
1163     {
1164     if(ui.screen_width_factor < -10000 ||
1165       ui.screen_width_factor > -500 ||
1166       ui.screen_height_factor <-10000 ||
1167       ui.screen_height_factor > -400)goto go_full_setup;
1168     }
1169   if( ui.font_scale < 1 ||
1170       ui.font_scale > 5 ||
1171       ui.check != UI_VERNR ||
1172       ui.operator_skil < OPERATOR_SKIL_NEWCOMER ||
1173       ui.operator_skil > OPERATOR_SKIL_EXPERT ||
1174       ui.soundcard_radio < SOUNDCARD_RADIO_UNDEFINED ||
1175       ui.soundcard_radio >= MAX_SOUNDCARD_RADIO)
1176     {
1177 go_full_setup:;
1178     printf("\n\nSetup file %s has errors",userint_filename);
1179     goto full_setup;
1180     }
1181   uiparm_change_flag=FALSE;
1182   free(parinfo);
1183   }
1184 }
1185 
1186