1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 
24 
25 // for Linux/svgalib.
26 // We set up the screen and mouse here and then we start
27 // the version independent main menu thread and the keyboard thread.
28 // We return here with lir_status=LIR_NEW_SCREEN in case the user
29 // wants a different screen resolution or LIR_UIPARMS if the
30 // user wants to change other system parameters.
31 
32 //#define UNINIT_MEMDATA 0x57
33 #define UNINIT_MEMDATA 0
34 #define MAX_MOUSE_CURSIZE 50
35 
36 
37 #include <sys/io.h>
38 #include <vga.h>
39 #include <vgagl.h>
40 #include <vgamouse.h>
41 #include <ctype.h>
42 #include <unistd.h>
43 #include <sys/mman.h>
44 #include <termios.h>
45 #include <sys/resource.h>
46 #include <string.h>
47 #include <signal.h>
48 #include <semaphore.h>
49 #include <pthread.h>
50 #include <fcntl.h>
51 #include <linux/fb.h>
52 #include <sys/mman.h>
53 #include <locale.h>
54 
55 
56 #include <sys/un.h>
57 #include <sys/socket.h>
58 #include <sys/stat.h>
59 #include <stdarg.h>
60 #include <linux/keyboard.h> /* to use KG_SHIFT and so on */
61 
62 
63 
64 #include "globdef.h"
65 #include "lconf.h"
66 #include "conf.h"
67 #include "rusage.h"
68 #include "thrdef.h"
69 #include "fdef.h"
70 #include "uidef.h"
71 #include "screendef.h"
72 #include "vernr.h"
73 #include "options.h"
74 #include "keyboard_def.h"
75 
76 
77 typedef struct {
78 unsigned short int red;
79 unsigned short int green;
80 unsigned short int blue;unsigned int pixel;
81 short int flag;
82 float total;
83 }PIXINFO;
84 
85 struct termios termios_pp;
86 int terminal_flag;
87 int gpm_fd;
88 struct fb_cmap *fb_palette;
89 int mouse_wheel_flag;
90 
main(int argc,char * argv[])91 int main(int argc, char *argv[])
92 {
93 int i,ir,j,k;
94 int xxprint;
95 char *parinfo;
96 FILE *file;
97 int *uiparm;
98 (void) *argv;
99 (void) argc;
100 setlocale(LC_ALL,"POSIX");
101 #if UNINIT_MEMDATA != 0
102   {
103   parinfo=(char*)(&uninit_mem_begin);
104   k=&uninit_mem_end-parinfo;
105   for(i=0; i<k; i++)parinfo[i]=UNINIT_MEMDATA;
106   }
107 #endif
108 i=system("reset");
109 terminal_flag=FALSE;
110 fb_palette=NULL;
111 gpm_fd=-1;
112 parinfo=(char *)getenv("TERM");
113 if(strncmp(parinfo,"xterm",5) == 0)
114   {
115   printf("Use xlinrad under X11!!\n");
116   exit(0);
117   }
118 // put something nonzero in scratch memory to make sure we not rely on
119 // it being zero when starting (this may help us detect bugs).
120 // Init svgalib and set it to text mode.
121 vga_simple_init();
122 // Permissions to write to the hardware have to be set
123 // before any new threads are started. Reason unknown........
124 init_os_independent_globals();
125 serport=-1;
126 // Allocate buffers for keyboard and mouse, then start their threads.
127 keyboard_buffer=malloc(KEYBOARD_BUFFER_SIZE*sizeof(int)+
128                      4*(MAX_MOUSE_CURSIZE+1)*sizeof(char));
129 behind_mouse=(char*)keyboard_buffer+KEYBOARD_BUFFER_SIZE*sizeof(int);
130 // Set the flags that tell whether daughter processes are running.
131 #ifdef THREAD_TIMERS
132 for(i=0; i<THREAD_MAX; i++)
133   {
134   thread_workload[i]=0;
135   thread_tottim1[i]=0;
136   thread_cputim1[i]=0;
137   thread_tottim2[i]=0;
138   thread_cputim2[i]=0;
139   }
140 #endif
141 lir_init_event(EVENT_KEYBOARD);
142 lir_init_event(EVENT_SYSCALL);
143 pthread_create(&thread_identifier_keyboard,NULL,(void*)thread_keyboard, NULL);
144 pthread_create(&thread_identifier_mouse,NULL,(void*)thread_mouse, NULL);
145 // Create a thread that will close the entire process in a controlled way
146 // in case lirerr() is called or the ESC key is pressed.
147 lir_init_event(EVENT_KILL_ALL);
148 pthread_create(&thread_identifier_kill_all,NULL,(void*)thread_kill_all, NULL);
149 uiparm=(int*)(&ui);
150 if(DUMPFILE)
151   {
152   dmp = fopen("dmp", "w");
153   DEB"\n******************************\n");
154   }
155 else
156   {
157   dmp=NULL;
158   }
159 os_flag=OS_FLAG_SVGALIB;
160 #if DARWIN == 0
161 xxprint=investigate_cpu();
162 #else
163 xxprint=0;
164 simd_present=0;
165 mmx_present=0;
166 no_of_processors=1;
167 #endif
168 file = fopen(userint_filename, "rb");
169 if (file == NULL)
170   {
171   printf("\n\nWELCOME TO LINRAD");
172   printf("\nThis message is not an error, but an indication that setup");
173   printf("\nhas not yet been done.");
174   print_procerr(xxprint);
175   printf("\nSetup file %s missing.",userint_filename);
176 full_setup:;
177   for(i=0; i<MAX_UIPARM; i++) uiparm[i]=0;
178   welcome_msg();
179   to_upper_await_keyboard();
180   if(lir_inkey != 'S' && lir_inkey != 'N' && lir_inkey != 'E') goto skip;
181   if(lir_inkey == 'N')
182     {
183     ui.operator_skil=OPERATOR_SKIL_NEWCOMER;
184     }
185   else
186     {
187     if(lir_inkey == 'S')
188       {
189       ui.operator_skil=OPERATOR_SKIL_NORMAL;
190       }
191     else
192       {
193       ui.operator_skil=OPERATOR_SKIL_EXPERT;
194       }
195     }
196   lin_global_uiparms(0);
197   if(kill_all_flag) goto exitmain;
198   uiparm_change_flag=TRUE;
199   ui.rx_input_mode=-1;
200   ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
201   ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
202   ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
203   ui.max_dma_rate=DEFAULT_MAX_DMA_RATE;
204   ui.min_dma_rate=DEFAULT_MIN_DMA_RATE;
205   ui.soundcard_radio=SOUNDCARD_RADIO_UNDEFINED;
206   ui.converter_mhz=0;
207   ui.converter_hz=0;
208   }
209 else
210   {
211   parinfo=malloc(4096);
212   if(parinfo == NULL)
213     {
214     lir_errcod=1078;
215     goto exitmain;
216     }
217   for(i=0; i<4096; i++) parinfo[i]=0;
218   ir=(int)fread(parinfo,1,4095,file);
219   fclose(file);
220   file=NULL;
221   if(ir >= 4095)
222     {
223     goto go_full_setup;
224     }
225   k=0;
226   for(i=0; i<MAX_UIPARM; i++)
227     {
228     while(parinfo[k]==' ' ||
229           parinfo[k]== '\n' )k++;
230     j=0;
231     while(parinfo[k]== uiparm_text[i][j])
232       {
233       k++;
234       j++;
235       }
236     if(uiparm_text[i][j] != 0)goto go_full_setup;
237     while(parinfo[k]!='[' && k< ir)k++;
238     sscanf(&parinfo[k],"[%d]",&uiparm[i]);
239     while(parinfo[k]!='\n' && k< ir)k++;
240     }
241   if( ui.check != UI_VERNR ||
242       ui.operator_skil < OPERATOR_SKIL_NEWCOMER ||
243       ui.operator_skil > OPERATOR_SKIL_EXPERT ||
244       ui.soundcard_radio < SOUNDCARD_RADIO_UNDEFINED ||
245       ui.soundcard_radio >= MAX_SOUNDCARD_RADIO)
246     {
247 go_full_setup:;
248     printf("\n\nSetup file %s has errors",userint_filename);
249     parinfo=chk_free(parinfo);
250     goto full_setup;
251     }
252   graphics_init();
253   init_font(ui.font_scale);
254   if(lir_errcod != 0)goto exitmain;
255   uiparm_change_flag=FALSE;
256   }
257 //extio_error=load_extio_library();
258 users_open_devices();
259 if(kill_all_flag) goto exitmain;
260 pthread_create(&thread_identifier_main_menu,NULL,
261                                               (void*)thread_main_menu, NULL);
262 file=freopen( "stderr.log", "w", stderr );
263 usleep(50000);
264 
265 lir_inkey=0;
266 
267 pthread_join(thread_identifier_main_menu,0);
268 exitmain:;
269 //unload_extio_library();
270 if(terminal_flag)
271   {
272   clear_keyboard();
273   tcsetattr(0, TCSANOW, &termios_pp);
274   }
275 if(gpm_fd>=0) close(gpm_fd);
276 printf( "\e[?25h" );	// restore cursor visibility
277 users_close_devices();
278 lir_close_serport();
279 pthread_cancel(thread_identifier_mouse);
280 pthread_join(thread_identifier_mouse,0);
281 lir_sleep(20000);
282 pthread_cancel(thread_identifier_keyboard);
283 pthread_join(thread_identifier_keyboard,0);
284 show_errmsg(0);
285 skip:;
286 printf("\nLeaving %s\n",PROGRAM_NAME);
287 if(dmp!=NULL)fclose(dmp);
288 munmap(mempix_char, framebuffer_screensize);
289 if(framebuffer_handle)close(framebuffer_handle);
290 if(fb_palette)free(fb_palette);
291 return lir_errcod;
292 }
293 
294 
graphics_init(void)295 void graphics_init(void)
296 {
297 int i, k;
298 unsigned short int *ipalette;
299 struct fb_var_screeninfo vinfo;
300 struct fb_fix_screeninfo finfo;
301 short unsigned int red[MAX_SVGA_PALETTE];
302 short unsigned int green[MAX_SVGA_PALETTE];
303 short unsigned int blue[MAX_SVGA_PALETTE];
304 short unsigned int transp[MAX_SVGA_PALETTE];
305 struct sockaddr_un addr;
306 struct MouseCaps caps;
307 struct termios termios_p;
308 framebuffer_screensize=0;
309 framebuffer_handle = open("/dev/fb0", O_RDWR);
310 if (!framebuffer_handle)
311   {
312   lirerr(1349);
313   return;
314   }
315 if (ioctl(framebuffer_handle, FBIOGET_VSCREENINFO, &vinfo))
316   {
317   lirerr(1351);
318   return;
319   }
320 color_depth=vinfo.bits_per_pixel;
321 framebuffer_screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
322 mempix_char = mmap(0, framebuffer_screensize, PROT_READ | PROT_WRITE, MAP_SHARED, framebuffer_handle, 0);
323 #if IA64 == 0
324 if ((int)mempix_char == -1)
325 #else
326 if ((long int)mempix_char == -1)
327 #endif
328   {
329   lirerr(1355);
330   return;
331   }
332 color_depth=vinfo.bits_per_pixel;
333 printf("color_depth=%d",color_depth);
334 tcgetattr(0, &termios_pp);
335 memcpy(&termios_p, &termios_pp, sizeof(termios_p));
336 terminal_flag=TRUE;
337 termios_p.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
338                                       | INLCR | IGNCR | ICRNL | IXON);
339 termios_p.c_oflag &= ~OPOST;
340 termios_p.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
341 termios_p.c_cflag &= ~(CSIZE | PARENB);
342 termios_p.c_cflag |= CS8;
343 tcsetattr(0, TCSANOW, &termios_p);
344 printf( "\e[?25l\n " ); // hide the cursor
345 // Open gpmctl. This will hide the gpm cursor.
346 gpm_fd=socket(AF_UNIX,SOCK_STREAM,0);
347 if(gpm_fd >= 0)
348   {
349   memset(&addr,0,sizeof(addr));
350   addr.sun_family=AF_UNIX;
351   strcpy(addr.sun_path, GPMCTL);
352   i=sizeof(addr.sun_family)+strlen(GPMCTL);
353   if(connect(gpm_fd,(struct sockaddr *)(&addr),i)<0 )
354     {
355     close(gpm_fd);
356     gpm_fd=open(GPMCTL,O_RDWR);
357     }
358   }
359 
360 
361 
362 
363 screen_width=vinfo.xres;
364 screen_height=vinfo.yres;
365 screen_totpix=screen_width*screen_height;
366 i=vga_getmousetype();
367 if(i == MOUSE_NONE)
368   {
369   lirerr(1354);
370   return;
371   }
372 
373 mouse_init("/dev/mouse",i,MOUSE_DEFAULTSAMPLERATE);
374 mouse_setdefaulteventhandler();
375 mouse_setxrange(0, screen_width-1);
376 mouse_setyrange(0, screen_height-1);
377 mouse_setwrap(MOUSE_NOWRAP);
378 lir_status=LIR_OK;
379 // Set up mouse and system parameters in case it has not been done already.
380 mouse_cursize=screen_height/80;
381 if(mouse_cursize > MAX_MOUSE_CURSIZE)mouse_cursize=MAX_MOUSE_CURSIZE;
382 if(ui.mouse_speed < 1)ui.mouse_speed=1;
383 if(ui.mouse_speed > 999)ui.mouse_speed=999;
384 mouse_setscale(ui.mouse_speed);
385 mouse_x=screen_width/2;
386 mouse_y=screen_height/2;
387 new_mouse_x=screen_width/2;
388 new_mouse_y=screen_height/2;
389 mouse_setposition( mouse_x, mouse_y);
390 if(mouse_getcaps(&caps))
391   {
392 // Failed! Old library version... Check the mouse type.
393   i=vga_getmousetype() & MOUSE_TYPE_MASK;
394   if(i == MOUSE_INTELLIMOUSE || i==MOUSE_IMPS2)
395     {
396     mouse_wheel_flag=1;
397     }
398   else
399     {
400     mouse_wheel_flag=0;
401     }
402   }
403 else
404   {
405 // If this is a mouse_wheel_flag mouse, interpret rx as a wheel
406   mouse_wheel_flag = ((caps.info & MOUSE_INFO_WHEEL) != 0);
407   }
408 if(mouse_wheel_flag)
409   {
410   mouse_setrange_6d(0,0, 0,0, 0, 0, -180,180, 0,0, 0,0, MOUSE_RXDIM);
411   }
412 
413 
414 
415 
416 if(screen_width < 640 || screen_height < 480)
417   {
418   lirerr(1242);
419   return;
420   }
421 switch (color_depth)
422   {
423   case 32:
424   case 24:
425   for(i=0; i<screen_totpix*4; i++)mempix_char[i]=0;
426 // ******************************************************************
427 // Rearrange the palette. It was designed for svgalib under Linux
428   for(i=0; i<3*MAX_SVGA_PALETTE; i++)
429     {
430     svga_palette[i]=(unsigned char)(svga_palette[i]<<2);
431     if(svga_palette[i] != 0) svga_palette[i]|=3;
432     }
433   break;
434 
435   case 16:
436   mempix_shi=(unsigned short int*)mempix_char;
437   for(i=0; i<screen_totpix; i++)mempix_shi[i]=0;
438 // ******************************************************************
439   ipalette=(unsigned short int*)(&svga_palette[0]);
440   for(i=0; i<256; i++)
441     {
442     k=svga_palette[3*i+2];
443     k&=0xfffe;
444     k<<=5;
445     k|=svga_palette[3*i+1];
446     k&=0xfffe;
447     k<<=6;
448     k|=svga_palette[3*i  ];
449     k>>=1;
450     ipalette[i]=(short unsigned int)k;
451     }
452   break;
453 
454 
455   case 8:
456   if (ioctl(framebuffer_handle, FBIOGET_FSCREENINFO, &finfo))
457     {
458     lirerr(1350);
459     return;
460     }
461   fb_palette=malloc(256*sizeof(fb_palette));
462   if(finfo.visual == FB_VISUAL_DIRECTCOLOR)
463     {
464     if (ioctl(framebuffer_handle, FBIOGETCMAP , &fb_palette))
465       {
466       free(fb_palette);
467       lirerr(1352);
468       return;
469       }
470     }
471   fb_palette->start=0;
472   fb_palette->len=MAX_SVGA_PALETTE;
473   for(i=0; i<MAX_SVGA_PALETTE; i++)
474     {
475     red[i]=(short unsigned int)(svga_palette[3*i+2]);
476     green[i]=(short unsigned int)(svga_palette[3*i+1]);
477     blue[i]=(short unsigned int)(svga_palette[3*i  ]);
478     transp[i]=0;
479     }
480   fb_palette->red=red;
481   fb_palette->green=green;
482   fb_palette->blue=blue;
483   fb_palette->transp=transp;
484 
485   vinfo.activate=FB_ACTIVATE_ALL|FB_CHANGE_CMAP_VBL;
486   ioctl(framebuffer_handle, FBIOPUT_VSCREENINFO, &vinfo);
487 
488   i=ioctl(framebuffer_handle, FBIOPUTCMAP , &fb_palette);
489 
490 
491 printf("\nioctl FBIOPUTCMAP returned %d\n",i);
492 
493 
494 
495 /*
496   defpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
497   lirpix=(PIXINFO*)malloc(sizeof(PIXINFO)*256);
498   pixdiff=(float*)malloc(256*256*sizeof(float));
499   lir_colormap=XCreateColormap(xdis, xwin, visual, AllocAll);
500   default_colormap = DefaultColormap(xdis, screen_num);
501 // Store the default colormap in defpix
502   for(id=0; id<256; id++)
503     {
504     xco.pixel=(long unsigned int)id;
505     k=XQueryColor (xdis,default_colormap,&xco);
506     defpix[id].red=xco.red;
507     defpix[id].green=xco.green;
508     defpix[id].blue=xco.blue;
509     defpix[id].flag=0;
510     defpix[id].pixel=(unsigned int)id;
511     defpix[id].total=(float)defpix[id].red*(float)defpix[id].red+
512                      (float)defpix[id].green*(float)defpix[id].green+
513                      (float)defpix[id].blue*(float)defpix[id].blue;
514     }
515 // svga_palette uses the six lowest bits for the colour intensities.
516 // shift left by 10 to move our data to occupy the six highest bits.
517 // Store the svgalib palette.
518   for(il=0; il<MAX_SVGA_PALETTE; il++)
519     {
520     lirpix[il].red=(short unsigned int)(svga_palette[3*il+2]<<2);
521     lirpix[il].green=(short unsigned int)(svga_palette[3*il+1]<<2);
522     lirpix[il].blue=(short unsigned int)(svga_palette[3*il  ]<<2);
523     if(lirpix[il].red != 0)lirpix[il].red|=3;
524     if(lirpix[il].green != 0)lirpix[il].green|=3;
525     if(lirpix[il].blue != 0)lirpix[il].blue|=3;
526     lirpix[il].red=(short unsigned int)(lirpix[il].red<<8);
527     lirpix[il].green=(short unsigned int)(lirpix[il].green<<8);
528     lirpix[il].blue=(short unsigned int)(lirpix[il].blue<<8);
529     lirpix[il].pixel=(unsigned int)il;
530     lirpix[il].flag=1;
531     lirpix[il].total=(float)lirpix[il].red*(float)lirpix[il].red+
532                      (float)lirpix[il].green*(float)lirpix[il].green+
533                      (float)lirpix[il].blue*(float)lirpix[il].blue;
534     }
535   for(il=MAX_SVGA_PALETTE; il<256; il++)
536     {
537     lirpix[il].red=0;
538     lirpix[il].green=0;
539     lirpix[il].blue=0;
540     lirpix[il].pixel=(unsigned int)il;
541     lirpix[il].flag=0;
542     }
543 #define M 0.00000001
544 #define N 0x100
545 // Sort lirpix in order of ascending total intensity.
546   for(il=0; il<MAX_SVGA_PALETTE-1; il++)
547     {
548     t1=0;
549     m=il;
550     for(kl=il; kl<MAX_SVGA_PALETTE; kl++)
551       {
552       if(lirpix[kl].total > t1)
553         {
554         t1=lirpix[kl].total;
555         m=kl;
556         }
557       }
558     tmppix=lirpix[il];
559     lirpix[il]=lirpix[m];
560     lirpix[m]=tmppix;
561     }
562 // Compute the similarity between lirpix and defpix and store in a matrix.
563   for(il=0; il<MAX_SVGA_PALETTE; il++)
564     {
565     for(id=0; id<256; id++)
566       {
567       t2=(float)(pow((float)(lirpix[il].red-defpix[id].red),2.0)+
568                  pow((float)(lirpix[il].green-defpix[id].green),2.0)+
569                  pow((float)(lirpix[il].blue-defpix[id].blue),2.0));
570       pixdiff[id+il*256]=t2;
571       }
572     }
573 // Reorder the default colormap for the diagonal elements
574 // of pixdiff (up to MAX_SVGA_PALETTE-1) to become as small
575 // as possible when stepping in the ascending order that
576 // lirpix currently is sorted in.
577   for(il=0; il<MAX_SVGA_PALETTE; il++)
578     {
579     t1=(float)BIG;
580     kd=0;
581     for(id=0; id<256; id++)
582       {
583       if(pixdiff[id+il*256] < t1)
584         {
585         t1=pixdiff[id+il*256];
586         kd=id;
587         }
588       }
589     tmppix=defpix[il];
590     defpix[il]=defpix[kd];
591     defpix[kd]=tmppix;
592     for(kl=0; kl<MAX_SVGA_PALETTE; kl++)
593       {
594       t1=pixdiff[kd+kl*256];
595       pixdiff[kd+kl*256]=pixdiff[il+kl*256];
596       pixdiff[il+kl*256]=t1;
597       }
598     }
599   for(i=0; i<MAX_SVGA_PALETTE; i++)
600     {
601     xco.pixel=defpix[i].pixel;
602     xco.red=lirpix[i].red;
603     xco.green=lirpix[i].green;
604     xco.blue=lirpix[i].blue;
605     xco.flags=DoRed|DoGreen|DoBlue;
606     xco.pad=0;
607     k=XStoreColor(xdis, lir_colormap, &xco);
608     if(k==0)
609       {
610       printf("\nPalette failed\n");
611       goto exitmain;
612       }
613     xpalette[lirpix[i].pixel]=(unsigned char)xco.pixel;
614     }
615   for(i=MAX_SVGA_PALETTE; i<256; i++)
616     {
617     xco.pixel=defpix[i].pixel;
618     xco.red=defpix[i].red;
619     xco.green=defpix[i].green;
620     xco.blue=defpix[i].blue;
621     xco.flags=DoRed|DoGreen|DoBlue;
622     xco.pad=0;
623     k=XStoreColor(xdis, lir_colormap, &xco);
624     if(k==0)
625       {
626       printf("\nPalette failed\n");
627       goto exitmain;
628       }
629     xpalette[i]=(unsigned char)lirpix[i].pixel;
630     }
631   XSetWindowColormap(xdis, xwin, lir_colormap);
632   free(defpix);
633   free(lirpix);
634   free(pixdiff);
635 */
636   break;
637 
638 
639   default:
640   printf("\nUnknown color depth: %d\n",color_depth);
641   lirerr(1353);
642   return;
643   }
644 }
645 
646 
647 
force_getchar(void)648 int force_getchar(void)
649 {
650 // Get a character from keyboard, but set a 0.1 s timeout
651 // and return -1 if no key was pressed.
652 struct termios term, oterm;
653 int c = 0;
654 // get the terminal settings
655 tcgetattr(0, &oterm);
656 // get a copy of the settings, which we modify
657 memcpy(&term, &oterm, sizeof(term));
658 // put the terminal in non-canonical mode, any
659 // reads timeout after 0.1 seconds or when a
660 // single character is read
661 term.c_lflag = term.c_lflag & (!ICANON);
662 term.c_cc[VMIN] = 0;
663 term.c_cc[VTIME] = 1;
664 tcsetattr(0, TCSANOW, &term);
665 // get input - timeout after 0.1 seconds or
666 // when one character is read. If timed out
667 // getchar() returns -1, otherwise it returns
668 // the character
669 c=getchar();
670 //   reset the terminal to original state
671 tcsetattr(0, TCSANOW, &oterm);
672 return c;
673 }
674 
675 
thread_keyboard(void)676 void thread_keyboard(void)
677 {
678 int c, i, k;
679 char s[80];
680 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
681 while(1)
682   {
683 // It is silly to use force_getchar here.
684 // We should set up stdin so it will return on each char of an ESC sequence.
685 // so we would not have to loop around at 10 Hz here.
686   c=getchar();
687   keyboard_buffer[keyboard_buffer_ptr]=c;
688   if(c == 27)
689     {
690 // Set the flag and wait a while to make it unlikely
691 // it will not be visible for the kill_all thread.
692 // We must not kill the keyboard thread while force_getchar() is
693 // executed because the changed terminal setting will survive
694 // after Linrad is finished and make the command line behave
695 // incorrectly.
696       {
697       c=force_getchar();
698       if(c == -1)
699         {
700 // The ESC key was pressed. Exit from Linrad NOW!
701         DEB"\nESC pressed");
702         if(ui.operator_skil == OPERATOR_SKIL_NEWCOMER && !kill_all_flag)
703           {
704           newcomer_escpress(0);
705 newco_esc:;
706           while(c != 'Y' && c != 'N')c=to_upper(getchar());
707           if(c=='N')
708             {
709             while(c!=-1)c=force_getchar();
710             newcomer_escpress(1);
711             goto next;
712             }
713           if(c != 'Y')goto newco_esc;
714           }
715         lir_set_event(EVENT_KILL_ALL);
716         while(!kill_all_flag)lir_sleep(3000);
717 check_threads:;
718         k=0;
719         for(i=0; i<THREAD_MAX; i++)
720           {
721           if(i != THREAD_SYSCALL &&
722              thread_command_flag[i] != THRFLAG_NOT_ACTIVE &&
723              thread_waitsem[i] == -2)
724             {
725             k++;
726             }
727           }
728         if(k != 0)
729           {
730           lir_sleep(30000);
731           goto check_threads;
732           }
733         keyboard_buffer[keyboard_buffer_ptr]=0;
734         keyboard_buffer_ptr=(keyboard_buffer_ptr+1)&
735                                                   (KEYBOARD_BUFFER_SIZE-1);
736         lir_sleep(10000);
737         lir_set_event(EVENT_KEYBOARD);
738         while(1)
739           {
740           lir_sleep(30000);
741           }
742         return;
743         }
744 // The ESC sequences are all [27],[91],.....
745       if(c == 91)
746         {
747         c=force_getchar();
748 // Arrow keys are:
749 // ARROW_UP=65
750 // ARROW_DOWN=66
751 // ARROW_RIGHT=67
752 // ARROW_LEFT=68
753         if(c >= 65 && c <= 68)
754           {
755           c+=ARROW_UP_KEY-65;
756           goto fkn_key_ok;
757           }
758         if(c >= 49 && c <= 54)
759           {
760           i=force_getchar();
761 // These keys have to be followed by 126
762 // HOME=49
763 // INSERT=50
764 // DELETE=51
765 // END=52
766 // PAGE_UP=53
767 // PAGE_DOWN=54
768           if(i == 126)
769             {
770             c+=HOME_KEY-49;
771             goto fkn_key_ok;
772             }
773           k=force_getchar();
774           if(k == 126)
775             {
776             if(c == 49)
777               {
778 // F6=55
779 // F7=56
780 // F8=57
781               if(i >= 55 && i <= 57)
782                 {
783                 c=i+F6_KEY-55;
784                 goto fkn_key_ok;
785                 }
786               }
787             if(c == 50)
788               {
789 // F9=48
790 // F10=49
791 // F10_PAD=50
792 // F11=51
793 // F12=52
794 // SHIFT_F1=53
795 // SHIFT_F2=54
796 // SHIFT_F2_PAD=55
797 // SHIFT_F3=56
798 // SHIFT_F4=57
799               if(i >= 48 && i <= 57)
800                 {
801                 c=i+F9_KEY-48;
802                 goto fkn_key_ok;
803                 }
804               }
805             if(c == 51)
806               {
807 // SHIFT_F5=49
808 // SHIFT_F6=50
809 // SHIFT_F7=51
810 // SHIFT_F8=52
811              if(i >= 49 && i <= 52)
812                 {
813                 c=i+SHIFT_F5_KEY-49;
814                 goto fkn_key_ok;
815                 }
816               }
817             }
818           sprintf(s,"ESC sequence):[27][91][%d][%d][%d]",c,i,k);
819           goto skip;
820           }
821 // PAUSE = 80
822         if(c == 80)
823           {
824           c=PAUSE_KEY;
825           goto fkn_key_ok;
826           }
827         if(c == 91)
828           {
829 
830           c=force_getchar();
831 // F1=65
832 // F2=66
833 // F3=67
834 // F4=68
835 // F5=69
836           if(c >= 65 && c <= 69)
837             {
838             c+=F1_KEY-65;
839             goto fkn_key_ok;
840             }
841           sprintf(s,"ESC sequence:[27][91][91][%d]",c);
842           goto skip;
843           }
844         sprintf(s,"ESC sequence:[27][91][%d]",c);
845         goto skip;
846         }
847 // ESC followed by something else than 91 (should never occur)
848       sprintf(s,"ESC sequence:[27][%d]",c);
849 skip:;
850       lir_text(1,5,s);
851       c=force_getchar();
852       if(c != -1)
853         {
854         i=0;
855         while(s[i]!=0 && i<70)i++;
856         sprintf(&s[i],"[%d]",c);
857         goto skip;
858         }
859       if(c == -1) goto next;
860 fkn_key_ok:;
861       keyboard_buffer[keyboard_buffer_ptr]=c;
862       }
863     }
864   keyboard_buffer_ptr=(keyboard_buffer_ptr+1)&(KEYBOARD_BUFFER_SIZE-1);
865   lir_sleep(10000);
866   lir_set_event(EVENT_KEYBOARD);
867 next:;
868   }
869 }
870 
thread_mouse(void)871 void thread_mouse(void)
872 {
873 int i, m, button, rx;
874 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
875 while(TRUE)
876   {
877 // **********************************************
878 // Wait for svgalib to report a mouse event
879   mouse_waitforupdate();
880 // We do nothing unless mouse_flag is set.
881   if(mouse_flag != 0)
882     {
883     button= mouse_getbutton();
884     mouse_getposition_6d(&new_mouse_x, &new_mouse_y, NULL, &rx, NULL, NULL);
885     if(rx!=0)
886       {
887       if (button & MOUSE_MIDDLEBUTTON)
888         {
889         m=bg.wheel_stepn;
890         if(rx > 0)
891           {
892           m++;
893           if(m>30)m=30;
894           }
895         else
896           {
897           m--;
898           if(m<-30)m=-30;
899           if(genparm[AFC_ENABLE]==0 && m<0)m=0;
900           }
901         bg.wheel_stepn=m;
902         sc[SC_SHOW_WHEEL]++;
903         make_modepar_file(GRAPHTYPE_BG);
904         }
905       else
906         {
907         if(rx > 0)
908           {
909           step_rx_frequency(1);
910           }
911         else
912           {
913           step_rx_frequency(-1);
914           }
915         }
916       }
917     if (button & MOUSE_LEFTBUTTON)
918       {
919       new_lbutton_state=1;
920       }
921     else
922       {
923       new_lbutton_state=0;
924       }
925     if (button & MOUSE_RIGHTBUTTON)
926       {
927       new_rbutton_state=1;
928       }
929     else
930       {
931       new_rbutton_state=0;
932       }
933     if( thread_status_flag[THREAD_SCREEN] == THRFLAG_SEM_WAIT ||
934         thread_status_flag[THREAD_SCREEN] == THRFLAG_ACTIVE ||
935         thread_status_flag[THREAD_SCREEN] == THRFLAG_IDLE)
936       {
937       if( new_mouse_x!=mouse_x || new_mouse_y!=mouse_y)
938         {
939         lir_set_event(EVENT_SCREEN);
940         }
941       check_mouse_actions();
942       }
943     }
944   }
945 }
946 
947