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