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