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 #include <unistd.h>
25 #include "globdef.h"
26 #include "uidef.h"
27 #include "fft1def.h"
28 #include "screendef.h"
29 #include "seldef.h"
30 #include "sigdef.h"
31 #include "rusage.h"
32 #include "thrdef.h"
33 #include "vernr.h"
34 #include "keyboard_def.h"
35 #include "options.h"
36 
37 unsigned char show_scro_color;
38 FILE *msg_file;
39 extern fpos_t file_startpos;
40 extern fpos_t file_playpos;
41 
42 // Define fseeko and ftello. Some old distributions, e.g. RedHat 9
43 // have the functions but not in the headers.
44 #ifndef fseeko
45 int fseeko(FILE *stream, off_t offset, int whence);
46 #endif
47 #ifndef ftello
48 off_t ftello(FILE *stream);
49 #endif
50 
51 
show_scro(int ix1,int iy1,int ix2,int iy2)52 void show_scro(int ix1,int iy1,int ix2,int iy2)
53 {
54 unsigned char cl;
55 if(ix1 < 0 || ix1 >= screen_width)return;
56 if(ix2 < 0 || ix2 >= screen_width)return;
57 if(show_scro_color==0)cl=12; else cl=10;
58 lir_hline(ix1,iy1,ix2,cl);
59 if(show_scro_color==2)cl=12; else cl=10;
60 lir_hline(ix1,iy2,ix2,cl);
61 if(show_scro_color==1)cl=12; else cl=10;
62 lir_line(ix1,iy1,ix1,iy2,cl);
63 if(show_scro_color==3)cl=12; else cl=10;
64 lir_line(ix2,iy1,ix2,iy2,cl);
65 }
66 
67 char *screensave;
68 
init_screensave(void)69 void init_screensave(void)
70 {
71 if(screensave_flag)return;
72 screensave=malloc(screen_width*screen_height);
73 if( screensave == NULL)
74   {
75   lirerr(1035);
76   return;
77   }
78 screensave_flag=TRUE;
79 pause_thread(THREAD_SCREEN);
80 lir_getbox(0,0,screen_width,screen_height,(MEMREF_T*)screensave);
81 lir_sched_yield();
82 }
83 
close_screensave(void)84 void close_screensave(void)
85 {
86 lir_putbox(0,0,screen_width,screen_height,(MEMREF_T*)screensave);
87 free(screensave);
88 screensave_flag=FALSE;
89 lir_sched_yield();
90 resume_thread(THREAD_SCREEN);
91 }
92 
edit_diskread_times(void)93 void edit_diskread_times(void)
94 {
95 char s[80];
96 int i, j, k, blk, line;
97 double filetime1, filetime2, blk_factor;
98 off_t fptr_pa;
99 off_t fptr_px;
100 off_t fptr_pb;
101 double dt1;
102 int diskread_timofday1;
103 int diskread_timofday2;
104 fptr_pa=0;
105 fptr_px=0;
106 diskread_pause_flag=1;
107 init_screensave();
108 if(kill_all_flag)return;
109 clear_screen();
110 settextcolor(15);
111 line=3;
112 lir_text(10,line,"EDIT times for playback of recorded file. (X to return)");
113 line +=2;
114 settextcolor(14);
115 lir_text(20,line,savefile_name);
116 line+=3;
117 settextcolor(7);
118 filetime1=diskread_time;
119 i=rint(filetime1);
120 j=i/(24*3600);
121 sprintf(s,"Day since Epoch=%d",j);
122 lir_text(0,line,s);
123 line++;
124 i%=24*3600;
125 diskread_timofday1=i;
126 j=i/3600;
127 i%=3600;
128 sprintf(s,"File starts at: %02d.%02d.%02d",j,i/60,i%60);
129 lir_text(0,line,s);
130 line++;
131 fseek(save_rd_file, 0, SEEK_END);
132 #if OSNUM == OSNUM_LINUX
133 fptr_pa=ftello(save_rd_file);
134 #endif
135 #if OSNUM == OSNUM_WINDOWS
136 fptr_pa=ftell(save_rd_file);
137 #endif
138 fsetpos(save_rd_file,&file_startpos);
139 #if OSNUM == OSNUM_LINUX
140 fptr_px=ftello(save_rd_file);
141 #endif
142 #if OSNUM == OSNUM_WINDOWS
143 fptr_px=ftell(save_rd_file);
144 #endif
145 if( (ui.rx_input_mode&DWORD_INPUT) == 0)
146   {
147   if( (ui.rx_input_mode&BYTE_INPUT) != 0)
148     {
149     blk=snd[RXAD].block_bytes>>1;
150     }
151   else
152     {
153     blk=snd[RXAD].block_bytes;
154     }
155   }
156 else
157   {
158   if( (ui.rx_input_mode&(BYTE_INPUT+FLOAT_INPUT)) != 0)
159     {
160     if( (ui.rx_input_mode&FLOAT_INPUT) == 0)
161       {
162       blk=3*(snd[RXAD].block_bytes>>2);
163       }
164     else
165       {
166       blk=snd[RXAD].block_bytes;
167       }
168     }
169   else
170     {
171     blk=save_rw_bytes;
172     }
173   }
174 filetime2=fptr_pa-fptr_px;
175 blk_factor=snd[RXAD].block_bytes;
176 blk_factor/=blk;
177 filetime2*=blk_factor;
178 filetime2=diskread_timofday1+filetime2/(snd[RXAD].framesize*ui.rx_ad_speed);
179 i=rint(filetime2);
180 i%=24*3600;
181 diskread_timofday2=i;
182 if(diskread_timofday2 < diskread_timofday1)diskread_timofday2+=24*3600;
183 j=i/3600;
184 i%=3600;
185 sprintf(s,"ends at: %02d.%02d.%02d",j,i/60,i%60);
186 lir_text(7,line,s);
187 line+=2;
188 get_start:;
189 clear_lines(line,line+3);
190 lir_text(0,line,"Start playback at (hh.mm.ss):");
191 i=lir_get_filename(31,line,s);
192 if(kill_all_flag)goto end_edit;
193 if(i == 0)
194   {
195   dt1=0;
196   clear_lines(line,line);
197   lir_text(0,line,"Starting from beginning of file");
198   goto start_0;
199   }
200 for(j=0; j<i; j++)
201   {
202   if(s[j]!='.' && (s[j] < '0' || s[j] > '9'))
203     {
204 errstart:;
205     settextcolor(12);
206     lir_text(10,line+2, "ERROR");
207     lir_text(10,line+3,press_any_key);
208     settextcolor(7);
209     to_upper_await_keyboard();
210     if(kill_all_flag)return;
211     if(lir_inkey == 'X')goto end_edit;
212     goto get_start;
213     }
214   }
215 sscanf(s,"%02d.%02d.%02d",&i,&j,&k);
216 if( i < 0 ||
217     i > 24 ||
218     j < 0 ||
219     j > 60 ||
220     k < 0 ||
221     k > 60)goto errstart;
222 dt1=(i*60+j)*60+k;
223 if(dt1 < diskread_timofday1)dt1+=24*3600;
224 if(dt1 >= diskread_timofday2)goto errstart;
225 dt1-=diskread_timofday1;
226 if(dt1 < 0)lirerr(32919);
227 dt1*=snd[RXAD].framesize*ui.rx_ad_speed/blk_factor;
228 start_0:;
229 // The data in the file starts at fptr_px and the last
230 // position in the file is fptr_pa. The corresponding times
231 // are diskread_timofday1 and diskread_timofday2
232 // Set fptr_pb to point at the selected start time.
233 fptr_pb=rint(dt1/blk);
234 diskread_block_counter=fptr_pb;
235 file_start_block=diskread_block_counter;
236 fptr_pb*=blk;
237 fptr_pb+=fptr_px;
238 #if OSNUM == OSNUM_LINUX
239 fseeko(save_rd_file, fptr_pb, SEEK_SET);
240 #endif
241 #if OSNUM == OSNUM_WINDOWS
242 fseek(save_rd_file, fptr_pb, SEEK_SET);
243 #endif
244 fgetpos(save_rd_file,&file_playpos);
245 lir_sched_yield();
246 line+=2;
247 get_stop:;
248 clear_lines(line,line+3);
249 lir_text(0,line,"Stop playback at (hh.mm.ss):");
250 i=lir_get_filename(30,line,s);
251 if(kill_all_flag)goto end_edit;
252 if(i == 0)
253   {
254 last_block:;
255   file_stop_block=-1;
256   goto end_edit;
257   }
258 for(j=0; j<i; j++)
259   {
260   if(s[j]!='.' && (s[j] < '0' || s[j] > '9'))
261     {
262 errstop:;
263     settextcolor(12);
264     lir_text(10,line+2, "ERROR");
265     lir_text(10,line+3,press_any_key);
266     settextcolor(7);
267     to_upper_await_keyboard();
268     if(kill_all_flag)return;
269     if(lir_inkey == 'X')goto end_edit;
270     goto get_stop;
271     }
272   }
273 sscanf(s,"%02d.%02d.%02d",&i,&j,&k);
274 if( i < 0 ||
275     i > 24 ||
276     j < 0 ||
277     j > 60 ||
278     k < 0 ||
279     k > 60)goto errstop;
280 dt1=(i*60+j)*60+k;
281 if(dt1 < diskread_timofday1)dt1+=24*3600;
282 if(dt1 >= diskread_timofday2)goto last_block;
283 dt1-=diskread_timofday1;
284 if(dt1 < 0)lirerr(32929);
285 dt1*=snd[RXAD].framesize*ui.rx_ad_speed;
286 file_stop_block=rint(dt1/snd[RXAD].block_bytes);
287 i=diskread_time+file_stop_block*snd[RXAD].block_frames/ui.rx_ad_speed;
288 i%=24*3600;
289 j=i/3600;
290 i%=3600;
291 sprintf(s,"%02d.%02d.%02d",j,i/60,i%60);
292 end_edit:;
293 close_screensave();
294 lir_refresh_screen();
295 diskread_pause_flag=0;
296 lir_sched_yield();
297 }
298 
newcomer_escpress(int clear)299 void newcomer_escpress(int clear)
300 {
301 if(clear == 0)
302   {
303   if(screensave_flag)
304     {
305     lir_sleep(10000);
306     if(keyboard_buffer_ptr == keyboard_buffer_used)
307       {
308       keyboard_buffer[keyboard_buffer_ptr]=0;
309       keyboard_buffer_ptr=(keyboard_buffer_ptr+1)&(KEYBOARD_BUFFER_SIZE-1);
310       }
311     lir_sleep(10000);
312     lir_set_event(EVENT_KEYBOARD);
313     while(thread_status_flag[THREAD_SCREEN] == THRFLAG_IDLE)
314       {
315       lir_refresh_screen();
316       lir_sleep(3000);
317       if(kill_all_flag) return;
318       }
319     }
320   init_screensave();
321   if(kill_all_flag)return;
322   clear_screen();
323   settextcolor(15);
324   lir_text(20,10,"ESC key pressed");
325   settextcolor(7);
326   lir_text(5,12,"Do you really want to exit from Linrad now ?  (Y/N)=>");
327   }
328 else
329   {
330   close_screensave();
331   }
332 lir_refresh_screen();
333 }
334 
help_screen_objects(void)335 void help_screen_objects(void)
336 {
337 int i, j;
338 #if(OSNUM == OSNUM_LINUX && RUSAGE_OLD==0)
339 int line;
340 char s[80];
341 #endif
342 // Make sure we are not in a mouse function.
343 mouse_time_wide=current_time();
344 mouse_time_narrow=mouse_time_wide;
345 if(mouse_task != -1)return;
346 lir_sched_yield();
347 if(mouse_task != -1)return;
348 mouse_time_wide=current_time();
349 mouse_time_narrow=mouse_time_wide;
350 lir_sched_yield();
351 if(mouse_task != -1)return;
352 mouse_inhibit=TRUE;
353 init_screensave();
354 if(kill_all_flag)return;
355 for(i=0; i<no_of_scro; i++)
356   {
357   if( scro[i].x1 <= mouse_x &&
358       scro[i].x2 >= mouse_x &&
359       scro[i].y1 <= mouse_y &&
360       scro[i].y2 >= mouse_y)
361     {
362     switch (scro[i].no)
363       {
364       case WIDE_GRAPH:
365       help_on_wide_graph();
366       break;
367 
368       case HIRES_GRAPH:
369       help_on_hires_graph();
370       break;
371 
372       case AFC_GRAPH:
373       help_on_afc_graph();
374       break;
375 
376       case BASEBAND_GRAPH:
377       help_on_baseband_graph();
378       break;
379 
380       case POL_GRAPH:
381       help_on_pol_graph();
382       break;
383 
384       case COH_GRAPH:
385       help_on_coherent_graph();
386       break;
387 
388       case EME_GRAPH:
389       help_on_eme_graph();
390       break;
391 
392       case FREQ_GRAPH:
393       help_on_freq_graph();
394       break;
395 
396       case METER_GRAPH:
397       help_on_meter_graph();
398       break;
399 
400       case TRANSMIT_GRAPH:
401       help_on_tx_graph();
402       break;
403 
404       case RADAR_GRAPH:
405       help_on_radar_graph();
406       break;
407       }
408     }
409   }
410 if(kill_all_flag) return;
411 if(lir_inkey != 0)
412   {
413   show_scro_color=0;
414 repeat:;
415   for(i=0; i<no_of_scro; i++)
416     {
417     show_scro(scro[i].x1,scro[i].y1,scro[i].x2,scro[i].y2);
418     switch (scro[i].no)
419       {
420       case WIDE_GRAPH:
421       for(j=4; j<MAX_WGBUTT; j++)
422         {
423         show_scro(wgbutt[j].x1,wgbutt[j].y1,wgbutt[j].x2,wgbutt[j].y2);
424         if(kill_all_flag) return;
425         }
426       break;
427 
428       case HIRES_GRAPH:
429       for(j=4; j<MAX_HGBUTT; j++)
430         {
431         if(hgbutt[j].x1 > 0)
432           {
433           show_scro(hgbutt[j].x1,hgbutt[j].y1,hgbutt[j].x2,hgbutt[j].y2);
434           if(kill_all_flag) return;
435           }
436         }
437 // The control bars are separate from the buttons.
438       show_scro(timf2_hg_xmin-2,timf2_hg_y[0],
439                                  timf2_hg_xmax+1,timf2_hg_y[0]+text_height-1);
440       if(kill_all_flag) return;
441       show_scro(hg_ston1_x2+2,hg_ston_y0,hg_first_xpixel,hg_stonbars_ytop);
442       if(kill_all_flag) return;
443       show_scro(hg.xleft+1,hg_ston_y0, hg_ston1_x2,hg_stonbars_ytop);
444       break;
445 
446       case AFC_GRAPH:
447       for(j=4; j<MAX_AGBUTT; j++)
448         {
449         show_scro(agbutt[j].x1,agbutt[j].y1,agbutt[j].x2,agbutt[j].y2);
450         if(kill_all_flag) return;
451         }
452 // The control bars are separate from the buttons.
453       show_scro(ag_ston_x1,ag_fpar_y0,ag_ston_x2,ag_fpar_ytop);
454       if(kill_all_flag) return;
455       show_scro(ag_lock_x1,ag_fpar_y0,ag_lock_x2,ag_fpar_ytop);
456       if(kill_all_flag) return;
457       show_scro(ag_srch_x1,ag_fpar_y0,ag_srch_x2,ag_fpar_ytop);
458       if(kill_all_flag) return;
459       break;
460 
461       case BASEBAND_GRAPH:
462       for(j=4; j<MAX_BGBUTT; j++)
463         {
464         show_scro(bgbutt[j].x1,bgbutt[j].y1,bgbutt[j].x2,bgbutt[j].y2);
465         if(kill_all_flag) return;
466         }
467 // The volume control bar:
468       show_scro(bg_vol_x1,bg_y0,bg_vol_x2,bg_ymax);
469       if(kill_all_flag) return;
470       break;
471 
472       case POL_GRAPH:
473       for(j=4; j<MAX_PGBUTT; j++)
474         {
475         show_scro(pgbutt[j].x1,pgbutt[j].y1,pgbutt[j].x2,pgbutt[j].y2);
476         if(kill_all_flag) return;
477         }
478       break;
479 
480       case COH_GRAPH:
481       for(j=4; j<MAX_CGBUTT; j++)
482         {
483         show_scro(cgbutt[j].x1,cgbutt[j].y1,cgbutt[j].x2,cgbutt[j].y2);
484         if(kill_all_flag) return;
485         }
486       break;
487 
488       case EME_GRAPH:
489       if(eme_active_flag != 0)
490         {
491         for(j=4; j<MAX_EGBUTT; j++)
492           {
493           show_scro(egbutt[j].x1,egbutt[j].y1,egbutt[j].x2,egbutt[j].y2);
494           if(kill_all_flag) return;
495           }
496         }
497       else
498         {
499         show_scro(egbutt[EG_MINIMISE].x1,egbutt[EG_MINIMISE].y1,
500                   egbutt[EG_MINIMISE].x2,egbutt[EG_MINIMISE].y2);
501         if(kill_all_flag) return;
502         }
503       break;
504 
505       case FREQ_GRAPH:
506       for(j=4; j<MAX_FGBUTT; j++)
507         {
508         show_scro(fgbutt[j].x1,fgbutt[j].y1,fgbutt[j].x2,fgbutt[j].y2);
509         if(kill_all_flag) return;
510         }
511       break;
512 
513       case METER_GRAPH:
514       for(j=4; j<MAX_MGBUTT; j++)
515         {
516         show_scro(mgbutt[j].x1,mgbutt[j].y1,mgbutt[j].x2,mgbutt[j].y2);
517         if(kill_all_flag) return;
518         }
519       break;
520 
521       case TRANSMIT_GRAPH:
522       for(j=4; j<MAX_TGBUTT; j++)
523         {
524         show_scro(tgbutt[j].x1,tgbutt[j].y1,tgbutt[j].x2,tgbutt[j].y2);
525         if(kill_all_flag) return;
526         }
527       break;
528       }
529     }
530   show_scro_color++;
531   if(show_scro_color > 3)show_scro_color=0;
532   lir_refresh_screen();
533   lir_sleep(400000);
534   test_keyboard();
535   if(kill_all_flag) goto help_scox;
536   process_current_lir_inkey();
537   if(kill_all_flag) goto help_scox;
538   if(lir_inkey == 0)goto repeat;
539   }
540 #if(OSNUM == OSNUM_LINUX && RUSAGE_OLD==0)
541 if(lir_inkey == F1_KEY || lir_inkey == '!')
542   {
543   clear_screen();
544   lir_text(15,0,"Threads within Linrad");
545   lir_text(0,2,"PID");
546   lir_text(10,2,"Name");
547   lir_text(20,2,"No");
548   line=3;
549   for(i=0; i<THREAD_MAX; i++)
550     {
551     if(thread_command_flag[i] > THRFLAG_NOT_ACTIVE  &&
552        thread_command_flag[i] < THRFLAG_RETURNED)
553       {
554       sprintf(s,"%d  ",thread_pid[i]);
555       lir_text(0,line,s);
556       lir_text(10,line,thread_names[i]);
557       sprintf(s,"%2d",i);
558       lir_text(20,line,s);
559       line++;
560       }
561     }
562   lir_refresh_screen();
563   test_keyboard();
564   process_current_lir_inkey();
565   while(!kill_all_flag && lir_inkey == 0)
566     {
567     test_keyboard();
568     lir_sleep(100000);
569     process_current_lir_inkey();
570     }
571   }
572 #endif
573 close_screensave();
574 lir_refresh_screen();
575 help_scox:;
576 resume_thread(THREAD_SCREEN);
577 mouse_inhibit=FALSE;
578 }
579 
write_from_msg_file(int * line,int msg_no,int screen_mode,int vernr)580 void write_from_msg_file(int *line, int msg_no,
581                                      int screen_mode, int vernr)
582 {
583 char s[512];
584 char chr;
585 int i,j,k;
586 msg_file=fopen(msg_filename, "r");
587 if(msg_file == NULL)
588   {
589   sprintf(s,"Could not find %s",msg_filename);
590   goto finish_err;
591   }
592 i=fread(&s,1,6,msg_file);
593 if(i!=6)
594   {
595   sprintf(s,"File %s empty",msg_filename);
596   goto finish_err_close;
597   }
598 s[6]=0;
599 sscanf(s,"%d",&k);
600 if(k != vernr)
601   {
602   sprintf(s,"Error %d. Wrong version number in %s",msg_no, msg_filename);
603   goto finish_err_close;
604   }
605 gtnum:;
606 i=fread(&s,1,1,msg_file);
607 if(i==0)
608   {
609   sprintf(s,"Could not find info no %d",msg_no);
610   goto finish_err_close;
611   }
612 if(s[0] != '[')goto gtnum;
613 j=0;
614 while(fread(&s[j],1,1,msg_file)==1 && s[j] != ']')j++;
615 s[j]=0;
616 sscanf(s,"%d",&k);
617 if(k != msg_no)goto gtnum;
618 sprintf(s,"[%d]",msg_no);
619 j=0;
620 while(s[j]!=0)j++;
621 j--;
622 gtrow:;
623 j++;
624 i=fread(&s[j],1,1,msg_file);
625 if( i==1 && s[j] != 10 && s[j] != '[' && j<255 )goto gtrow;
626 chr=s[j];
627 if(chr== '[' || chr==10)
628   {
629   s[j]=0;
630   }
631 else
632   {
633   s[j+1]=0;
634   }
635 if(screen_mode!=0)
636   {
637   lir_text(0,line[0],s);
638   }
639 else
640   {
641   printf("\n%s",s);
642   DEB"\n%s",s);
643   }
644 line[0]++;
645 if(chr != '[' && i==1)
646   {
647   j=-1;
648   goto gtrow;
649   }
650 goto finish_ok;
651 finish_err_close:;
652 fclose(msg_file);
653 finish_err:;
654 if(screen_mode!=0)
655   {
656   lir_text(0,line[0],s);
657   }
658 else
659   {
660   printf("\n%s",s);
661   DEB"\n%s",s);
662   }
663 line[0]++;
664 sprintf(s,"Error[%d] No info available in %s",msg_no,msg_filename);
665 if(screen_mode!=0)
666   {
667   lir_text(0,line[0],s);
668   }
669 else
670   {
671   printf("\n%s\n",s);
672   DEB"\n%s",s);
673   fflush(stdout);
674   lir_sync();
675   }
676 line[0]++;
677 finish_ok:;
678 if(screen_mode == 2)
679   {
680   if(os_flag == OSNUM_LINUX)
681     {
682     lir_text(15,line[0]+2,"Exit with ctlC");
683     }
684   else
685     {
686     lir_text(15,line[0]+2,
687        "Escape by clicking with the mouse mouse on the X in the title bar");
688     }
689   if(os_flag == OSNUM_WINDOWS)
690     {
691     lir_text(15,line[0]+3,"or with ESC from keyboard.");
692     }
693   }
694 lir_refresh_screen();
695 }
696 
show_errmsg(int screen_mode)697 void show_errmsg(int screen_mode)
698 {
699 char s[80];
700 int line;
701 if(lir_errcod == 0)
702   {
703   clear_screen();
704   lir_text(3,3,"Closing.");
705   lir_refresh_screen();
706   return;
707   }
708 if(screen_mode != 0)
709   {
710   settextcolor(15);
711   clear_screen();
712   }
713 sprintf(s,"INTERNAL ERROR: %d",lir_errcod);
714 if(screen_mode)
715   {
716   lir_text(0,2,s);
717   }
718 else
719   {
720   printf("\n%s",s);
721   DEB"\n%s",s);
722   }
723 msg_filename="/usr/local//share/linrad/errors.lir";
724 line=3;
725 write_from_msg_file(&line, lir_errcod, screen_mode, ERROR_VERNR);
726 }
727 
728 
help_message(int msg_no)729 void help_message(int msg_no)
730 {
731 int i, line;
732 if(msg_no < 0)return;
733 msg_filename="/usr/local//share/linrad/help.lir";
734 line=0;
735 settextcolor(15);
736 clear_screen();
737 #if INTERNAL_GEN_FILTER_TEST == TRUE
738   i=1;
739 #else
740   i=2;
741 #endif
742 if(msg_no != 1)
743   {
744   write_from_msg_file(&line, msg_no, TRUE, HELP_VERNR);
745   line+=2;
746   lir_text(0,line,
747              "Press F1 or ! for KEYBOARD COMMANDS. Any other key to exit help.");
748   await_keyboard();
749   if(lir_inkey != F1_KEY && lir_inkey != '!')goto ex;
750   line=0;
751   clear_screen();
752   }
753 write_from_msg_file(&line, i, TRUE, HELP_VERNR);
754 await_processed_keyboard();
755 ex:;
756 lir_inkey=0;
757 settextcolor(7);
758 clear_screen();
759 }
760