1 /*
2  * Tlf - contest logging program for amateur radio operators
3  * Copyright (C) 2013-2015 Ervin Hegedüs - HA2OS <airween@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 /* ------------------------------------------------------------
20  *        Handle QTC panel, receive and send QTC, write to log
21  *
22  *--------------------------------------------------------------*/
23 
24 
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "callinput.h"
31 #include "cw_utils.h"
32 #include "genqtclist.h"
33 #include "get_time.h"
34 #include "ignore_unused.h"
35 #include "keyer.h"
36 #include "keystroke_names.h"
37 #include "lancode.h"
38 #include "nicebox.h"		// Includes curses.h
39 #include "qtc_log.h"
40 #include "qtcutil.h"
41 #include "qtcvars.h"		// Includes globalvars.h
42 #include "rtty.h"
43 #include "sendbuf.h"
44 #include "speedupndown.h"
45 #include "time_update.h"
46 #include "tlf_panel.h"
47 #include "ui_utils.h"
48 #include "write_keyer.h"
49 /* check direction clause macro
50  * direction should be RECV (1) or SEND (2), see tlf.h
51  */
52 #define DIRCLAUSE (direction == RECV) || (direction == SEND && (activefield == 0 || activefield == 2))
53 
54 
55 void init_qtc_panel();
56 void draw_qtc_panel();
57 void start_qtc_recording();
58 void stop_qtc_recording();
59 void clear_help_block();
60 void show_help_msg();
61 void showfield(int fidx);
62 void modify_field(int pressed);
63 void delete_from_field(int dir);
64 void shift_left(char *fieldval, int shift);
65 void show_status(int idx);
66 void number_fields();
67 void put_qtc();
68 void replace_spaces(char *src, char *tempc);
69 void show_sendto_lines();
70 void recalc_qtclist();
71 void show_rtty_lines();
72 void fill_qtc_times(char *time);
73 
74 extern char hiscall[];
75 extern char lastcall[];
76 extern int trxmode;
77 extern int digikeyer;
78 extern int nr_qsos;
79 
80 static int record_run = -1;		/* was recording already started? */
81 
82 t_qtclist qtclist;
83 t_qtcreclist qtcreclist;
84 
85 t_qtc_ry_line qtc_ry_lines[QTC_RY_LINE_NR];
86 int qtc_ry_currline = 0;
87 int qtc_ry_capture;
88 int qtc_ry_copied;
89 
90 struct t_qtc_store_obj *qtc_temp_obj;  /* temp object to help to maintain
91 					  the QTC hash */
92 
93 
94 enum {
95     QTCRECVWINBG = 32,
96     QTCRECVLINE,
97     QTCRECVINVLINE,
98     QTCRECVCURRLINE,
99     QTCRECVBG,
100 };
101 
102 #define LINE_INVERTED  		(COLOR_PAIR(QTCRECVINVLINE) | A_BOLD)
103 #define LINE_CURRINVERTED 	(COLOR_PAIR(QTCRECVCURRLINE) | A_BOLD)
104 #define LINE_CURRNORMAL  	(COLOR_PAIR(QTCRECVCURRLINE) | A_NORMAL)
105 #define LINE_NORMAL  		(COLOR_PAIR(QTCRECVLINE) | A_NORMAL)
106 
107 WINDOW *qtcwin;
108 PANEL *qtc_panel;
109 WINDOW *ry_win;
110 PANEL *ry_panel;
111 WINDOW *ry_help_win;
112 PANEL *ry_help_panel;
113 
114 
115 int activefield;
116 // array values: hor position, cursor position, field len to fill with spaces
117 int pos[6][3] = {{3, 3, 15}, {3, 6, 4}, {8, 8, 2}, {3, 3, 4}, {8, 8, 14}, {24, 24, 4}};
118 int curpos = 0;
119 int curfieldlen = 0;
120 static char prevqtccall[15] = "";
121 
122 char help_rec_msgs[7][26] = {
123     "Enter callsign",
124     "Enter the QTC serial",
125     "Enter the QTC number",
126     "Enter the time",
127     "Enter the CALL",
128     "Enter the SERIAL",
129     ""
130 };
131 char help_send_msgs[7][26] = {
132     "Enter callsign",
133     "",
134     "Enter the QTC number",
135     "Press ENTER to send QTC",
136     "",
137     "",
138     "Press CTRL+S to SAVE!"
139 };
140 
141 char *qtccallsign;
142 int *qtccount;
143 int qtccurrdirection;
144 char qtchead[32];
145 
146 
147 /* Init qtc panels and windows if needed, set used colorpairs */
init_qtc_panel()148 void init_qtc_panel() {
149     static int qtcpanel_initialized = 0;
150 
151     if (!qtcpanel_initialized) {
152 	qtcwin = newwin(14, 75, 9, 2);
153 	qtc_panel = new_panel(qtcwin);
154 	hide_panel(qtc_panel);
155 
156 	ry_win = newwin(14, 40, 9, 37);
157 	ry_panel = new_panel(ry_win);
158 	hide_panel(ry_panel);
159 
160 	ry_help_win = newwin(5, 75, 4, 2);
161 	ry_help_panel = new_panel(ry_help_win);
162 	hide_panel(ry_help_panel);
163 
164 	qtcpanel_initialized = 1;
165     }
166 
167     init_pair(QTCRECVWINBG,   COLOR_BLUE,   COLOR_GREEN);
168     init_pair(QTCRECVLINE,    COLOR_WHITE,  COLOR_BLUE);
169     init_pair(QTCRECVINVLINE, COLOR_YELLOW, COLOR_CYAN);
170     init_pair(QTCRECVCURRLINE, COLOR_YELLOW, COLOR_MAGENTA);
171     init_pair(QTCRECVBG,      COLOR_BLUE,   COLOR_CYAN);
172 }
173 
174 /* draw the panel content */
draw_qtc_panel(int direction)175 void draw_qtc_panel(int direction) {
176     int i, j;
177 
178     show_panel(qtc_panel);
179     top_panel(qtc_panel);
180 
181     werase(qtcwin);
182 
183     wnicebox(qtcwin, 0, 0, 12, 33, qtchead);
184 
185     sprintf(qtchead, "HELP");
186     wnicebox(qtcwin, 0, 35, 12, 38, qtchead);
187 
188     wbkgd(qtcwin, (chtype)(A_NORMAL | COLOR_PAIR(QTCRECVWINBG)));
189 
190     wattrset(qtcwin, LINE_INVERTED);
191     mvwprintw(qtcwin, 1, 1, "                                 ");
192     /* the first visible and used line is the qtc serial and count
193      * it differs in RECV and SEND direction, these two lines sets them
194      */
195     if (direction == RECV) {
196 	mvwprintw(qtcwin, 2, 1, "      /                          ");
197     }
198     if (direction == SEND) {
199 	mvwprintw(qtcwin, 2, 1, "     %d/%2d                        ",
200 		  qtclist.serial, qtclist.count);
201     }
202 
203     showfield(0);	// QTC CALL
204     if (direction == RECV) {
205 	showfield(1);	// QTC serial
206     }
207     showfield(2);	// QTC nr of row
208 
209     clear_help_block();
210 
211     /* if the direction is RECV, set the fields on the opened QTC window */
212     if (direction == RECV) {
213 	for (i = 0; i < QTC_LINES; i++) {
214 	    wattrset(qtcwin, LINE_INVERTED);
215 	    mvwprintw(qtcwin, i + 3, 1, "                                 ");
216 	    for (j = 0; j < 3; j++) {
217 		showfield((i * 3) + j + 3);	// QTC fields...
218 	    }
219 	}
220 	number_fields();
221     }
222     /* same function, but it's a littlebit more complex, therefore that's in an external function */
223     if (direction == SEND) {
224 	show_sendto_lines();
225     }
226 
227     /* if the direction is RECV, and mode is DIGIMODE,
228      * show the current CAPTURE MODE
229      */
230     if (qtccurrdirection == RECV) {
231 	wattrset(qtcwin, LINE_INVERTED);
232 
233 	if (trxmode == DIGIMODE) {
234 	    if (qtc_ry_capture == 0) {
235 		mvwprintw(qtcwin, 2, 11, "CAPTURE OFF");
236 	    } else {
237 		mvwprintw(qtcwin, 2, 11, "CAPTURE ON ");
238 		show_rtty_lines();
239 	    }
240 	} else {
241 	    if (qtcrec_record == 1) {
242 		mvwprintw(qtcwin, 2, 11, "RECORD OFF  ");
243 	    }
244 	}
245 	wattrset(qtcwin, LINE_NORMAL);
246     }
247 
248     showfield(activefield);
249     curpos = 0;
250 
251     refreshp();
252 }
253 
254 
255 /* start recording */
start_qtc_recording()256 void start_qtc_recording() {
257     char reccommand[100] = "";
258     char tempc[40];
259 
260     if (record_run < 0 && qtcrec_record == 1
261 	    && strlen((char *)qtcrec_record_command) > 0) {
262 	strcpy(reccommand, qtcrec_record_command[0]);
263 	get_time();
264 	strftime(tempc, 60, "%y%m%d%H%M%S.wav", time_ptr);
265 	strcat(reccommand, tempc);
266 	strcat(reccommand, qtcrec_record_command[1]);
267 	record_run = system(reccommand);
268 	if (record_run > -1 && qtcrec_record == 1) {
269 	    mvwprintw(qtcwin, 2, 11, "RECORD ON   ");
270 	}
271     }
272 }
273 
274 /* stop recording */
stop_qtc_recording()275 void stop_qtc_recording() {
276     char reccommand[100] = "";
277 
278     if (qtcrec_record == 1 && strlen((char *)qtcrec_record_command_shutdown) > 0) {
279 	strcpy(reccommand, "pkill -SIGINT -n ");
280 	strcat(reccommand, qtcrec_record_command_shutdown);
281 	IGNORE(system(reccommand));;
282 	record_run = -1;
283 	if (qtcrec_record == 1) {
284 	    mvwprintw(qtcwin, 2, 11, "RECORD OFF  ");
285 	}
286     }
287 }
288 
fill_qtc_callsign(int direction,char * tcall)289 void fill_qtc_callsign(int direction, char *tcall) {
290     if (direction == RECV) {
291 	strcpy(qtcreclist.callsign, tcall);
292     }
293     if (direction == SEND) {
294 	strcpy(qtclist.callsign, tcall);
295     }
296 }
297 
fill_qtc_times(char * time)298 void fill_qtc_times(char *time) {
299     int i;
300     int len;
301     int afield;
302 
303     if (trxmode != DIGIMODE && qtccurrdirection == RECV) {
304 	afield = (activefield - 3) / 3;
305 	if (strlen(time) >= 2) {
306 	    len = 2;
307 	} else {
308 	    len = strlen(time);
309 	}
310 	for (i = afield + 1; i < *qtccount; i++) {
311 	    strncpy(qtcreclist.qtclines[i].time, time, len);
312 	    qtcreclist.qtclines[i].time[len] = '\0';
313 	    showfield(3 + (i * 3));
314 	}
315     }
316 }
317 
fill_lazy_line(t_qtcrecline * recline)318 void fill_lazy_line(t_qtcrecline *recline) {
319     int i;
320 
321     // fill time field
322     for (i = strlen(recline->time); i < 4; i++) {
323 	recline->time[i + 1] = '\0';
324 	recline->time[i] = '?';
325     }
326 
327     // fill callsign field
328     for (i = strlen(recline->callsign); i < 3; i++) {
329 	recline->callsign[i + 1] = '\0';
330 	recline->callsign[i] = '?';
331     }
332 
333     // fill serial field
334     for (i = strlen(recline->serial); i < 1; i++) {
335 	recline->serial[i + 1] = '\0';
336 	recline->serial[i] = '?';
337     }
338 
339 }
340 
341 /* prepare data for RECV operation */
prepare_for_recv()342 void prepare_for_recv() {
343     int i;
344 
345     /* if the callsign field is empty, or the callsign field has
346      * been changed in main window, then it needs to clean up
347      * all received QTC info
348      */
349     if (strcmp(qtcreclist.callsign, prevqtccall) != 0 ||
350 	    strlen(qtcreclist.callsign) == 0) {
351 	qtcreclist.count = 0;
352 	qtcreclist.serial = 0;
353 	qtcreclist.confirmed = 0;
354 	qtcreclist.sentcfmall = 0;
355 	for (i = 0; i < QTC_LINES; i++) {
356 	    qtcreclist.qtclines[i].status = 0;
357 	    qtcreclist.qtclines[i].time[0] = '\0';
358 	    qtcreclist.qtclines[i].callsign[0] = '\0';
359 	    qtcreclist.qtclines[i].serial[0] = '\0';
360 	    qtcreclist.qtclines[i].receivedtime[0] = '\0';
361 	    qtcreclist.qtclines[i].confirmed = 0;
362 	}
363 	activefield = 0;
364 	qtc_ry_copied = 0;
365 	stop_qtc_recording();
366     }
367 
368     if (qtcreclist.count == 0) {
369 	activefield = 0;
370     }
371 
372     /* save the previous qtc callsign */
373     g_strlcpy(prevqtccall, qtcreclist.callsign, sizeof(prevqtccall));
374     qtccallsign = qtcreclist.callsign;
375 
376     /* save the address of the counter of receive QTC block */
377     qtccount = &qtcreclist.count;
378 
379     /* set the QTC win header */
380     sprintf(qtchead, "QTC receive");
381 }
382 
383 
384 /* prepare data for SEND operation */
prepare_for_send()385 void prepare_for_send() {
386 
387     /* if the callsign field in main window had been changed, it needs
388      * to clean up the qtc structure */
389     if (strcmp(qtclist.callsign, prevqtccall) != 0 ||
390 	    strlen(qtclist.callsign) == 0 || qtclist.count == 0) {
391 
392 	qtc_temp_obj = qtc_get(qtclist.callsign);
393 	genqtclist(qtclist.callsign, (10 - (qtc_temp_obj->total)));
394 
395 	activefield = 0;
396     }
397 
398     /* save the current callsign to previous call variable */
399     g_strlcpy(prevqtccall, qtclist.callsign, sizeof(prevqtccall));
400     qtccallsign = qtclist.callsign;
401 
402     /* save the address of the counter of SEND qtc structure */
403     qtccount = &qtclist.count;
404 
405     /* set the QTC win header */
406     sprintf(qtchead, "QTC send");
407 }
408 
qtc_main_panel(int direction)409 void qtc_main_panel(int direction) {
410     char tempc[40];
411     int i, x;
412     int tfi, tlen = 0;
413     int currqtc = -1;
414     attr_t attributes;
415     short cpair;
416 
417 
418     /* fill the callsign fields of the current qtc direction structure
419      * with hiscall or the last call if hiscall is empty
420      */
421     if (strlen(hiscall) > 0) {
422 	fill_qtc_callsign(direction, hiscall);
423     } else if (strlen(lastcall) > 0) {
424 	fill_qtc_callsign(direction, lastcall);
425     }
426 
427     /* save the value of the direction variable */
428     qtccurrdirection = direction;
429 
430     /* here are the mandatory steps, if the direction is RECV */
431     if (direction == RECV) {
432 	prepare_for_recv();
433     }
434 
435     /* here are the mandatory steps, if the direction is SEND */
436     if (direction == SEND) {
437 	prepare_for_send();
438     }
439 
440     init_qtc_panel();
441     draw_qtc_panel(direction);
442 
443     i = 1;
444 
445     x = -1;
446     /* main loop */
447     while (x != ESCAPE) {
448 
449 	while (x < 1) {
450 
451 	    usleep(5000);
452 	    time_update();
453 	    if (trxmode == DIGIMODE && digikeyer != NO_KEYER) {
454 		show_rtty();
455 	    }
456 	    x = key_poll();
457 
458 	}
459 
460 	switch (x) {
461 	    // Ctrl-T (^T)
462 	    case CTRL_T:
463 		if (trxmode == DIGIMODE) {
464 		    show_rtty_lines();
465 		}
466 
467 	    // Up Arrow
468 	    case KEY_UP:
469 		if (direction == RECV) {
470 		    if (activefield > 0) {	// nr of QTC record field idx
471 			if (activefield == 1 || activefield == 2) {
472 			    activefield = 0;
473 			    showfield(1);
474 			    showfield(2);
475 			} else if (activefield == 3 || activefield == 4) {
476 			    activefield -= 2;
477 			    showfield(activefield + 2);
478 			} else {
479 			    activefield -= 3;
480 			    showfield(activefield + 3);
481 			}
482 		    }
483 		    showfield(activefield);
484 		    curpos = 0;
485 		}
486 		if (direction == SEND && ((trxmode != DIGIMODE
487 					   && qtclist.totalsent < *qtccount) || (trxmode == DIGIMODE
488 						   && qtclist.totalsent == *qtccount))) {
489 		    switch (activefield) {
490 			case 0:
491 			    activefield = 12;
492 			    show_help_msg(activefield);
493 			    showfield(0);
494 			    wattrset(qtcwin, LINE_CURRINVERTED);
495 			    mvwprintw(qtcwin, activefield, 4, "%s", qtclist.qtclines[9].qtc);
496 			    break;
497 			case 2:
498 			    activefield = 0;
499 			    showfield(2);
500 			    showfield(0);
501 			    break;
502 			case 3:
503 			    activefield = 2;
504 			    showfield(2);
505 			    wattrset(qtcwin, LINE_NORMAL);
506 			    mvwprintw(qtcwin, activefield + 1, 4, "%s", qtclist.qtclines[0].qtc);
507 			    break;
508 			case 4 ... 12:
509 			    show_help_msg(activefield);
510 			    wattrset(qtcwin, LINE_NORMAL);
511 			    mvwprintw(qtcwin, activefield, 4, "%s",
512 				      qtclist.qtclines[(activefield - 3)].qtc);
513 			    activefield--;
514 			    wattrset(qtcwin, LINE_CURRINVERTED);
515 			    mvwprintw(qtcwin, activefield, 4, "%s",
516 				      qtclist.qtclines[(activefield - 3)].qtc);
517 			    break;
518 		    }
519 		}
520 		break;
521 
522 	    // Down Arrow
523 	    case KEY_DOWN:
524 		if (direction == RECV) {
525 		    if (activefield < 30) {	// last line serial field idx
526 			if (activefield == 0) {
527 			    activefield = 1;
528 			    showfield(0);
529 			} else if (activefield == 1 || activefield == 2) {
530 			    activefield += 2;
531 			    showfield(1);
532 			    showfield(2);
533 			} else {
534 			    activefield += 3;
535 			    showfield(activefield - 3);
536 			}
537 		    }
538 		    showfield(activefield);
539 		    curpos = 0;
540 		}
541 		if (direction == SEND && ((trxmode != DIGIMODE
542 					   && qtclist.totalsent < *qtccount) || (trxmode == DIGIMODE
543 						   && qtclist.totalsent == *qtccount))) {
544 		    switch (activefield) {
545 			case 0:
546 			    activefield = 2;
547 			    showfield(0);
548 			    showfield(2);
549 			    break;
550 			case 2:
551 			    activefield = 3;
552 			    show_help_msg(activefield);
553 			    showfield(2);
554 			    wattrset(qtcwin, LINE_CURRINVERTED);
555 			    mvwprintw(qtcwin, activefield, 4, "%s", qtclist.qtclines[0].qtc);
556 			    break;
557 			case 3 ... 11:
558 			    show_help_msg(activefield);
559 			    wattrset(qtcwin, LINE_NORMAL);
560 			    mvwprintw(qtcwin, activefield, 4, "%s",
561 				      qtclist.qtclines[(activefield - 3)].qtc);
562 			    activefield++;
563 			    wattrset(qtcwin, LINE_CURRINVERTED);
564 			    mvwprintw(qtcwin, activefield, 4, "%s",
565 				      qtclist.qtclines[(activefield - 3)].qtc);
566 			    break;
567 			case 12:
568 			    activefield = 0;
569 			    wattrset(qtcwin, LINE_NORMAL);
570 			    mvwprintw(qtcwin, 14, 4, "%s", qtclist.qtclines[9].qtc);
571 			    showfield(0);
572 			    break;
573 		    }
574 		}
575 		break;
576 
577 	    // Left Arrow
578 	    case KEY_LEFT:
579 		if (DIRCLAUSE) {
580 		    if (curpos < curfieldlen) {	// curpos is a shift, means lenght - position
581 			curpos++;
582 			showfield(activefield);
583 		    }
584 		}
585 		break;
586 
587 	    // Right Arrow
588 	    case KEY_RIGHT:
589 		if (DIRCLAUSE) {
590 		    if (curpos > 0) {
591 			curpos--;
592 			showfield(activefield);
593 		    }
594 		}
595 		break;
596 
597 	    // <Enter>
598 	    case '\n':
599 	    case KEY_ENTER:
600 		if (activefield > 2) {
601 		    if (direction == RECV) {
602 			currqtc = ((activefield - 3) / 3);
603 			if ((qtcreclist.qtclines[currqtc].status == 0 &&
604 				strlen(qtcreclist.qtclines[currqtc].time) == 4 &&
605 				strlen(qtcreclist.qtclines[currqtc].callsign) > 0 &&
606 				strlen(qtcreclist.qtclines[currqtc].serial) > 0)
607 				||
608 				qtc_recv_lazy == 1
609 			   ) {
610 			    if (qtc_recv_lazy == 1) {
611 				fill_lazy_line(&qtcreclist.qtclines[currqtc]);
612 				showfield(3 * (currqtc + 1));
613 				showfield((3 * (currqtc + 1)) + 1);
614 				showfield((3 * (currqtc + 1)) + 2);
615 			    }
616 
617 			    get_time();
618 			    tempc[0] = '\0';
619 			    strftime(tempc, 40, "%d-%b-%y %H:%M", time_ptr);
620 			    g_strlcpy(qtcreclist.qtclines[currqtc].receivedtime, tempc, 16);
621 			    qtcreclist.qtclines[currqtc].status = 2;
622 			    show_status(currqtc);
623 			    if (currqtc < *qtccount) {
624 				if (trxmode == DIGIMODE) {
625 				    qtcreclist.qtclines[currqtc].confirmed = 1; // compatibility for other modes
626 				    qtcreclist.confirmed++;
627 				    activefield += 3;	// go to next line exch field
628 				    showfield(activefield - 3);
629 				} else {
630 				    if (qtcreclist.qtclines[currqtc].confirmed == 0) {
631 					qtcreclist.qtclines[currqtc].confirmed = 1;
632 					qtcreclist.confirmed++;
633 					if (trxmode == CWMODE) {
634 					    sendmessage(qtc_recv_msgs[2]);
635 					}
636 					if (trxmode == SSBMODE) {
637 					    play_file(qtc_phrecv_message[2]);
638 					}
639 				    }
640 				    tfi = (activefield - 3) % 3;
641 				    //activefield++;	// go to next line time field
642 				    activefield += (3 - tfi);
643 				    showfield(activefield - (3 - tfi));
644 				}
645 				showfield(activefield);
646 			    }
647 			} else if (qtcreclist.qtclines[currqtc].status == 1 &&
648 				   qtcreclist.qtclines[currqtc].confirmed != 1) {
649 			    if (trxmode == CWMODE) {
650 				sendmessage(qtc_recv_msgs[7]);
651 			    }
652 			    if (trxmode == SSBMODE) {
653 				play_file(qtc_phrecv_message[7]);
654 			    }
655 			    if (trxmode == DIGIMODE) {
656 				char *str = g_strdup_printf("%s %02d %02d\n",
657 							    g_strchomp(qtc_recv_msgs[7]),
658 							    currqtc + 1, currqtc + 1);
659 				sendmessage(str);
660 				g_free(str);
661 			    }
662 			}
663 
664 			if (*qtccount > 0 && qtcreclist.confirmed == *qtccount) {
665 			    if (qtcreclist.sentcfmall == 0) {
666 				qtcreclist.sentcfmall = 1;
667 				log_recv_qtc_to_disk(nr_qsos);
668 				if (record_run > -1) {
669 				    stop_qtc_recording();
670 				}
671 				if (trxmode == DIGIMODE || trxmode == CWMODE) {
672 				    sendmessage(qtc_recv_msgs[9]);
673 				}
674 				if (trxmode == SSBMODE) {
675 				    play_file(qtc_phrecv_message[9]);
676 				}
677 			    }
678 			    x = ESCAPE;	// <Escape> close the window
679 			}
680 		    }
681 		    if (direction == SEND && trxmode != DIGIMODE) {
682 			if (qtclist.qtclines[activefield - 3].sent == 0) {
683 			    qtclist.qtclines[activefield - 3].sent = 1;
684 			    get_time();
685 			    tempc[0] = '\0';
686 			    strftime(tempc, 40, "%d-%b-%y %H:%M", time_ptr);
687 			    g_strlcpy(qtclist.qtclines[activefield - 3].senttime, tempc, 16);
688 			    qtclist.qtclines[activefield - 3].senttime[15] = '\0';
689 			    qtclist.totalsent++;
690 			}
691 			tempc[0] = '\0';
692 			replace_spaces(qtclist.qtclines[activefield - 3].qtc, tempc);
693 			if (trxmode == CWMODE) {
694 			    sendmessage(tempc);
695 			}
696 
697 			mvwprintw(qtcwin, activefield, 30, "*");
698 			qtclist.qtclines[activefield - 3].flag = 1;
699 			// scroll down if not at end of qtclist:
700 			if (activefield - 3 < *qtccount - 1) {
701 			    wattrset(qtcwin, LINE_NORMAL);
702 			    mvwprintw(qtcwin, activefield, 4, "%s",
703 				      qtclist.qtclines[(activefield - 3)].qtc);
704 			    activefield++;
705 			    wattrset(qtcwin, LINE_CURRINVERTED);
706 			    mvwprintw(qtcwin, activefield, 4, "%s",
707 				      qtclist.qtclines[(activefield - 3)].qtc);
708 			}
709 			if (*qtccount > 0 && qtclist.totalsent == *qtccount) {
710 			    wattrset(qtcwin, LINE_INVERTED);
711 			    mvwprintw(qtcwin, 2, 11, "CTRL+S to SAVE!");
712 			    refreshp();
713 			    show_help_msg(6);
714 			}
715 		    }
716 		}
717 		if (activefield == 2) {
718 		    if (direction == RECV &&
719 			    strlen(qtcreclist.callsign) > 0 &&
720 			    qtcreclist.serial > 0 &&
721 			    qtcreclist.count > 0 &&
722 			    qtcreclist.confirmed == 0
723 		       ) {
724 			if (trxmode == CWMODE) {
725 			    sendmessage(qtc_recv_msgs[1]);
726 			}
727 			if (trxmode == SSBMODE) {
728 			    play_file(qtc_phrecv_message[1]);
729 			}
730 			start_qtc_recording();
731 			activefield++;
732 			showfield(activefield);
733 		    }
734 		}
735 		if (trxmode == DIGIMODE) {
736 		    if (direction == SEND && (activefield == 0 || activefield == 2)
737 			    && qtclist.totalsent == 0) {
738 			if (qtc_send_msgs[1][strlen(qtc_send_msgs[1]) - 1] == 10) {
739 			    qtc_send_msgs[1][strlen(qtc_send_msgs[1]) - 1] = '\0';
740 			}
741 			tlen = strlen(qtc_send_msgs[1]) - 5; // len("sr/nr") = 5
742 			char tmess[300], timec[40];
743 			int ql;
744 			tmess[0] = '\0';
745 			if (tlen > 0 && strncmp(qtc_send_msgs[1] + tlen, "sr/nr", 5) == 0) {
746 			    g_strlcpy(tempc, qtc_send_msgs[1], tlen);
747 			    sprintf(tmess, "%s %d/%d %s %d/%d\n",
748 				    tempc, qtclist.serial, *qtccount, tempc,
749 				    qtclist.serial, *qtccount);
750 			}
751 			timec[0] = '\0';
752 			get_time();
753 			strftime(timec, 40, "%d-%b-%y %H:%M", time_ptr);
754 
755 			for (ql = 0; ql < *qtccount; ql++) {
756 			    qtclist.qtclines[ql].sent = 1;
757 			    g_strlcpy(qtclist.qtclines[ql].senttime, timec, 16);
758 			    qtclist.totalsent++;
759 
760 			    tempc[0] = '\0';
761 			    replace_spaces(qtclist.qtclines[ql].qtc, tempc);
762 			    strcat(tmess, tempc);
763 			    mvwprintw(qtcwin, ql + 3, 30, "*");
764 			    qtclist.qtclines[ql].flag = 1;
765 
766 			}
767 			keyer_append(tmess);
768 			write_keyer();
769 			wattrset(qtcwin, LINE_INVERTED);
770 			mvwprintw(qtcwin, 2, 11, "CTRL+S to SAVE!");
771 			refreshp();
772 			show_help_msg(6);
773 
774 			showfield(activefield);
775 		    } else {
776 			if (direction == SEND) {
777 			    tempc[0] = '\0';
778 			    replace_spaces(qtclist.qtclines[activefield - 3].qtc, tempc);
779 			    sendmessage(tempc);
780 			}
781 		    }
782 		}
783 		if (activefield == 0) {
784 		    start_qtc_recording();
785 		}
786 		if (activefield < 2) {
787 		    if (direction == RECV) {
788 			activefield++;
789 			showfield(activefield - 1);
790 			showfield(activefield);
791 		    }
792 		}
793 		break;
794 
795 	    // Ctrl-S (^S), save QTC
796 	    case CTRL_S:
797 		if (qtccurrdirection == SEND && *qtccount > 0
798 			&& qtclist.totalsent == *qtccount) {
799 		    log_sent_qtc_to_disk(nr_qsos);
800 		    wattrset(qtcwin, LINE_INVERTED);
801 		    mvwprintw(qtcwin, 2, 11, "QTC's have been saved!");
802 		    prevqtccall[0] = '\0';
803 		    qtccallsign[0] = '\0';
804 		    refreshp();
805 		    sleep(1);
806 		    x = ESCAPE;	// <Escape> close the window
807 
808 		}
809 		if (qtccurrdirection == RECV && trxmode == DIGIMODE) {
810 		    qtc_ry_capture = 1;
811 		    wattr_get(qtcwin, &attributes, &cpair, NULL);
812 		    wattrset(qtcwin, LINE_INVERTED);
813 		    mvwprintw(qtcwin, 2, 11, "CAPTURE ON ");
814 		    wattrset(qtcwin, attributes);
815 		    showfield(activefield);
816 		    refreshp();
817 		    show_rtty_lines();
818 		}
819 		break;
820 
821 	    // Ctrl-E (^E), end capture
822 	    case CTRL_E:
823 		if (qtccurrdirection == RECV && trxmode == DIGIMODE) {
824 		    qtc_ry_capture = 0;
825 		    wattr_get(qtcwin, &attributes, &cpair, NULL);
826 		    wattrset(qtcwin, LINE_INVERTED);
827 		    mvwprintw(qtcwin, 2, 11, "CAPTURE OFF");
828 		    wattrset(qtcwin, attributes);
829 		    showfield(activefield);
830 		    refreshp();
831 		}
832 		break;
833 
834 	    // F1...F10
835 	    case KEY_F(1) ... KEY_F(10):
836 		if (trxmode == CWMODE || trxmode == DIGIMODE) {
837 		    if (direction == RECV) {
838 			sendmessage(qtc_recv_msgs[x - KEY_F(1)]); /* 0-9 */
839 
840 			/* start recording */
841 			if (trxmode == CWMODE && strncmp(qtc_recv_msgs[x - KEY_F(1)], "QRV", 3) == 0) {
842 			    start_qtc_recording();
843 			}
844 
845 			/* stop recording */
846 			if (trxmode == CWMODE
847 				&& strncmp(qtc_recv_msgs[x - KEY_F(1)], "QSL ALL", 7) == 0 && record_run > -1) {
848 			    stop_qtc_recording();
849 			}
850 
851 			if (trxmode == DIGIMODE
852 				&& strncmp(qtc_recv_msgs[x - KEY_F(1)], "QRV", 3) == 0) {
853 			    qtc_ry_capture = 1;
854 			    wattr_get(qtcwin, &attributes, &cpair, NULL);
855 			    wattrset(qtcwin, LINE_INVERTED);
856 			    mvwprintw(qtcwin, 2, 11, "CAPTURE ON ");
857 			    wattrset(qtcwin, attributes);
858 			    showfield(activefield);
859 			    refreshp();
860 			    show_rtty_lines();
861 			}
862 		    }
863 
864 		    if (direction == SEND && strlen(qtc_send_msgs[x - KEY_F(1)]) > 0) {
865 			if (qtc_send_msgs[x - KEY_F(1)][strlen(qtc_send_msgs[x - KEY_F(
866 				1)]) - 1] == '\n') {
867 			    qtc_send_msgs[x - KEY_F(1)][strlen(qtc_send_msgs[x - KEY_F(1)]) - 1] = 0;
868 			}
869 			tlen = strlen(qtc_send_msgs[x - KEY_F(1)]) - 5; // len("sr/nr") = 5
870 			char tmess[60];
871 			tmess[0] = '\0';
872 			if (tlen > 0 && strncmp(qtc_send_msgs[x - KEY_F(1)] + tlen, "sr/nr", 5) == 0) {
873 			    g_strlcpy(tempc, qtc_send_msgs[x - KEY_F(1)], tlen);
874 			    sprintf(tmess, "%s %d/%d ", tempc, qtclist.serial, *qtccount);
875 			    sendmessage(tmess);
876 			} else if ((activefield - 3) >= 0) {
877 			    if (x - KEY_F(1) == 4) {	// F5, TIME
878 				strncpy(tmess, qtclist.qtclines[activefield - 3].qtc, 5);
879 				tmess[5] = '\0';
880 				sendmessage(tmess);
881 			    }
882 			    if (x - KEY_F(1) == 5) {	// F6, CALLSIGN
883 				strncpy(tmess, qtclist.qtclines[activefield - 3].qtc + 5, 13);
884 				for (i = 12; tmess[i] == ' '; i--)
885 				    ;
886 				tmess[i + 1] = ' ';
887 				tmess[i + 2] = '\0';
888 				sendmessage(tmess);
889 			    }
890 			    if (x - KEY_F(1) == 6) {	// F7, SERIAL
891 				strncpy(tmess, qtclist.qtclines[activefield - 3].qtc + 20, 4);
892 				tmess[4] = ' ';
893 				tmess[5] = '\0';
894 				sendmessage(tmess);
895 			    }
896 			} else {
897 			    sendmessage(qtc_send_msgs[x - KEY_F(1)]);
898 			}
899 		    }
900 
901 		}
902 		if (trxmode == SSBMODE) {
903 		    if (direction == RECV) {
904 			if (x == KEY_F(2)) { // F2, "QRV"
905 			    start_qtc_recording();
906 			}
907 			if (x == KEY_F(10) && record_run > -1) { // F10, "QSL ALL"
908 			    stop_qtc_recording();
909 			}
910 			play_file(qtc_phrecv_message[x - KEY_F(1)]);
911 		    }
912 		    if (direction == SEND) {
913 			play_file(qtc_phsend_message[x - KEY_F(1)]);
914 		    }
915 		}
916 
917 		break;
918 
919 	    // <Delete>, Keypad <Del>
920 	    case KEY_DC:
921 		if (DIRCLAUSE) {
922 		    delete_from_field(0);
923 		}
924 		if (direction == SEND && activefield > 2 && trxmode != DIGIMODE) {
925 		    qtclist.qtclines[activefield - 3].sent = 0;
926 		    qtclist.qtclines[activefield - 3].flag = 0;
927 		    wattrset(qtcwin, LINE_CURRNORMAL);
928 		    mvwprintw(qtcwin, activefield, 30, " ");
929 		    qtclist.totalsent--;
930 		}
931 		break;
932 
933 	    // <Tab>
934 	    case TAB:
935 		if (direction == RECV) {
936 		    if (trxmode == DIGIMODE) {
937 			if (activefield == 32) {
938 			    activefield = 0;
939 			    showfield(32);
940 			} else {
941 			    activefield++;
942 			    showfield(activefield - 1);
943 			}
944 		    } else {
945 			if ((activefield < 3) || (activefield - 3) % 3 < 2) {
946 			    activefield++;
947 			    showfield(activefield - 1);
948 			} else {	/* (activefield-3)%3 == 2*/
949 			    activefield -= 2;
950 			    showfield(activefield + 2);
951 			}
952 		    }
953 		    showfield(activefield);
954 		}
955 		if (direction == SEND) {
956 		    switch (activefield) {
957 			case 0:
958 			    activefield = 2;
959 			    showfield(0);
960 			    showfield(2);
961 			    break;
962 			case 2:
963 			    activefield = 0;
964 			    showfield(2);
965 			    showfield(0);
966 			    break;
967 			default:
968 			    break;
969 		    }
970 		}
971 		curpos = 0;
972 		break;
973 
974 	    // Shift <Tab>
975 	    case KEY_BTAB:
976 		if (direction == RECV) {
977 		    if (trxmode == DIGIMODE) {
978 			if (activefield == 0) {
979 			    activefield = 32;
980 			    showfield(0);
981 			} else {
982 			    activefield--;
983 			    showfield(activefield + 1);
984 			}
985 		    } else {
986 			if ((activefield > 0 && activefield < 3) ||
987 				((activefield - 3) % 3 > 0)) {
988 			    activefield--;
989 			    showfield(activefield + 1);
990 			} else {		/* (activefield-3)%3 == 0) */
991 			    activefield += 2;
992 			    showfield(activefield - 2);
993 			}
994 		    }
995 		    showfield(activefield);
996 		}
997 		if (direction == SEND) {
998 		    switch (activefield) {
999 			case 0:
1000 			    activefield = 2;
1001 			    showfield(0);
1002 			    showfield(2);
1003 			    break;
1004 			case 2:
1005 			    activefield = 0;
1006 			    showfield(2);
1007 			    showfield(0);
1008 			    break;
1009 			default:
1010 			    break;
1011 		    }
1012 		}
1013 		curpos = 0;
1014 		break;
1015 
1016 	    // <Space>
1017 	    case SPACE:
1018 		if (DIRCLAUSE) {
1019 		    if (direction == RECV) {
1020 			if (activefield > 2) {
1021 			    if (activefield % 3 == 2) {
1022 				activefield -= 2;
1023 				showfield(activefield + 2);
1024 			    } else {
1025 				activefield++;
1026 				showfield(activefield - 1);
1027 			    }
1028 			    showfield(activefield);
1029 			}
1030 			if (activefield == 2) {
1031 			    if (strlen(qtcreclist.callsign) > 0 &&
1032 				    qtcreclist.serial > 0 &&
1033 				    qtcreclist.count > 0 &&
1034 				    qtcreclist.confirmed == 0
1035 			       ) {
1036 				if (trxmode == CWMODE) {
1037 				    sendmessage(qtc_recv_msgs[1]);
1038 				}
1039 				if (trxmode == SSBMODE) {
1040 				    play_file(qtc_phrecv_message[1]);
1041 				}
1042 				start_qtc_recording();
1043 				activefield++;
1044 				showfield(activefield);
1045 			    }
1046 			}
1047 			if (activefield < 2) {
1048 			    if (activefield == 0) {
1049 				start_qtc_recording();
1050 			    }
1051 			    activefield++;
1052 			    showfield(activefield - 1);
1053 			    showfield(activefield);
1054 			}
1055 		    }
1056 		}
1057 		break;
1058 
1059 	    // Numerals
1060 	    case '0' ... '9':
1061 		if (DIRCLAUSE) {
1062 		    modify_field(x);
1063 		}
1064 		break;
1065 
1066 	    /*case 65 ... 90:	// letters
1067 	    	modify_field(x);
1068 	    	break;*/
1069 
1070 	    // Convert lower case to upper case
1071 	    case 'a' ... 'z':
1072 		if (DIRCLAUSE) {
1073 		    modify_field(x - 32);
1074 		}
1075 		break;
1076 
1077 	    // Slash
1078 	    case '/':
1079 		if (DIRCLAUSE) {
1080 		    modify_field(x);
1081 		}
1082 		break;
1083 
1084 	    // Query
1085 	    case '?':
1086 		if (DIRCLAUSE) {
1087 		    modify_field(x);
1088 		}
1089 		break;
1090 
1091 	    // <Backspace>
1092 	    case KEY_BACKSPACE:
1093 		if (DIRCLAUSE) {
1094 		    delete_from_field(1);
1095 		}
1096 		break;
1097 
1098 	    // <Page-Up>
1099 	    case KEY_PPAGE:
1100 		speedup();
1101 		attron(COLOR_PAIR(C_HEADER) | A_STANDOUT);
1102 		mvprintw(0, 14, "%2u", GetCWSpeed());
1103 		break;
1104 
1105 	    // <Page-Down>
1106 	    case KEY_NPAGE:
1107 		speeddown();
1108 		attron(COLOR_PAIR(C_HEADER) | A_STANDOUT);
1109 		mvprintw(0, 14, "%2u", GetCWSpeed());
1110 		break;
1111 
1112 	    // Comma or Ctrl-K (^K), keyboard window
1113 	    case ',':
1114 	    case 11:
1115 		mvprintw(5, 0, "");
1116 		keyer();
1117 		x = 0;
1118 		break;
1119 
1120 	    // Ctrl-L (^L), mark callsign for late QTC
1121 	    case CTRL_L:
1122 		if (strlen(g_strstrip(qtccallsign)) > 3) {
1123 		    qtc_inc(g_strstrip(qtccallsign), QTC_LATER);
1124 		    sprintf(tempc, "%s;L\n", qtccallsign);
1125 		    send_lan_message(QTCFLAG, tempc);
1126 		}
1127 		break;
1128 
1129 	    // Ctrl-N (^N), mark callsign for explicit NO QTC
1130 	    case CTRL_N:
1131 		if (strlen(g_strstrip(qtccallsign)) > 3) {
1132 		    qtc_inc(g_strstrip(qtccallsign), QTC_NO);
1133 		    sprintf(tempc, "%s;N\n", qtccallsign);
1134 		    send_lan_message(QTCFLAG, tempc);
1135 		}
1136 		break;
1137 
1138 	    // Ctrl-F (^F), fill time fields with first 2 chars
1139 	    case CTRL_F:
1140 		if (activefield > 2) {
1141 		    fill_qtc_times(qtcreclist.qtclines[(activefield - 3) / 3].time);
1142 		    showfield(activefield);
1143 		}
1144 		break;
1145 
1146 	    // Ctrl-R (^R), start/stop recording
1147 	    case CTRL_R:
1148 		if (direction == RECV) {
1149 		    if (record_run < 0) {
1150 			start_qtc_recording();
1151 			showfield(activefield);
1152 		    } else {
1153 			stop_qtc_recording();
1154 		    }
1155 		}
1156 	}
1157 	refreshp();
1158 	if (x != ESCAPE) {
1159 	    x = 0;
1160 	}
1161     }
1162     hide_panel(qtc_panel);
1163 }
1164 
showfield(int fidx)1165 void showfield(int fidx) {
1166 
1167     char fieldval[20], filled[20];
1168     int qtcrow, winrow, fi, posidx, i;
1169 
1170     fieldval[0] = '\0';
1171 
1172     posidx = 0;
1173     if (fidx == 0) {
1174 	sprintf(fieldval, "%s", qtccallsign);
1175 	winrow = 1;
1176 	posidx = 0;
1177 	qtc_temp_obj = qtc_get(qtccallsign);
1178 	put_qtc();
1179     } else if (fidx == 1) {
1180 	sprintf(fieldval, "%4d", qtcreclist.serial);
1181 	winrow = 2;
1182 	posidx = 1;
1183     } else if (fidx == 2) {
1184 	sprintf(fieldval, "%d", *qtccount);
1185 	winrow = 2;
1186 	posidx = 2;
1187     } else {
1188 	fi = fidx - 3;
1189 	winrow = (fi / 3) + 3;
1190 	qtcrow = winrow - 3;
1191 	switch (fi % 3) {
1192 	    case 0:
1193 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].time);
1194 		posidx = 3;
1195 		break;
1196 	    case 1:
1197 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].callsign);
1198 		posidx = 4;
1199 		break;
1200 	    case 2:
1201 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].serial);
1202 		posidx = 5;
1203 		break;
1204 	}
1205 	show_status(qtcrow);
1206     }
1207     curfieldlen = strlen(fieldval);
1208 
1209     for (i = 0; i < pos[posidx][2]; i++) {
1210 	filled[i] = ' ';
1211     }
1212     filled[i] = '\0';
1213     if (fidx == activefield) {
1214 	wattrset(qtcwin, LINE_CURRINVERTED);
1215     } else {
1216 	wattrset(qtcwin, LINE_NORMAL);
1217     }
1218 
1219     mvwprintw(qtcwin, winrow, pos[posidx][0], filled);
1220     mvwprintw(qtcwin, winrow, pos[posidx][0], "%s", fieldval);
1221     if (fidx == activefield) {
1222 	show_help_msg(posidx);
1223 	if (pos[posidx][0] == pos[posidx][1]) {
1224 	    wmove(qtcwin, winrow, (pos[posidx][1] + strlen(fieldval)) - curpos);
1225 	} else {
1226 	    wmove(qtcwin, winrow, pos[posidx][1] - curpos);
1227 	}
1228     }
1229 }
1230 
modify_field(int pressed)1231 void modify_field(int pressed) {
1232     char fieldval[16];
1233     int fi, winrow, qtcrow, posidx, stridx;
1234 
1235     memset(fieldval, '\0', 15);
1236 
1237     posidx = 0;
1238     if (activefield == 0 && (isalnum(pressed) || pressed == '/')
1239 	    && strlen(qtccallsign) < pos[0][2] - 1) {
1240 	qtccallsign[strlen(qtccallsign) - curpos] = pressed;
1241 	if (curpos > 0) {
1242 	    curpos--;
1243 	}
1244 	recalc_qtclist();
1245 	showfield(0);
1246     } else if (activefield == 1 && isdigit(pressed)) {
1247 	sprintf(fieldval, "%d", (qtcreclist.serial) * 10);
1248 	fieldval[strlen(fieldval) - (1 + curpos)] = pressed;
1249 	if (curpos > 0) {
1250 	    curpos--;
1251 	}
1252 	if (strlen(fieldval) <= pos[1][2]) {
1253 	    qtcreclist.serial = atoi(fieldval);
1254 	    showfield(1);
1255 	}
1256     } else if (activefield == 2 && isdigit(pressed)) {
1257 	sprintf(fieldval, "%d", (*qtccount) * 10);
1258 	fieldval[strlen(fieldval) - (1 + curpos)] = pressed;
1259 	if (curpos > 0) {
1260 	    curpos--;
1261 	}
1262 	if (strlen(fieldval) <= pos[2][2] && atoi(fieldval) <= 10) {
1263 	    qtc_temp_obj = qtc_get(qtccallsign);
1264 	    if (qtccurrdirection == SEND) {
1265 		if (*qtccount != atoi(fieldval)) {
1266 		    if ((atoi(fieldval) + (qtc_temp_obj->total)) >= 10) {
1267 			sprintf(fieldval, "%d", (10 - (qtc_temp_obj->total)));
1268 		    }
1269 		    *qtccount = genqtclist(qtccallsign, atoi(fieldval));
1270 		    show_sendto_lines();
1271 		    put_qtc();
1272 		}
1273 	    }
1274 	    if (qtccurrdirection == RECV) {
1275 		if ((atoi(fieldval) + (qtc_temp_obj->total)) >= 10) {
1276 		    sprintf(fieldval, "%d", (10 - (qtc_temp_obj->total)));
1277 		}
1278 		*qtccount = atoi(fieldval);
1279 	    }
1280 	    number_fields();
1281 	    showfield(2);
1282 	}
1283     } else if (activefield >= 3 && activefield <= 32) {
1284 	fi = activefield - 3;
1285 	winrow = (fi / 3) + 3;
1286 	qtcrow = winrow - 3;
1287 	stridx = fi % 3;
1288 	switch (stridx) {
1289 	    case 0:
1290 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].time);
1291 		posidx = 3;
1292 		break;
1293 	    case 1:
1294 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].callsign);
1295 		posidx = 4;
1296 		break;
1297 	    case 2:
1298 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].serial);
1299 		posidx = 5;
1300 		break;
1301 	}
1302 	if (pressed == '?') {
1303 	    qtcreclist.qtclines[qtcrow].status = 1;	// set incomplete the qtc status
1304 	    show_status(qtcrow);
1305 	}
1306 	if ((((stridx == 0 || stridx == 2) && (isdigit(pressed) || pressed == '?'))
1307 		|| stridx == 1) && strlen(fieldval) < pos[posidx][2]) {
1308 
1309 	    fieldval[strlen(fieldval) - curpos] = pressed;
1310 	    switch (stridx) {
1311 		case 0:
1312 		    strcpy(qtcreclist.qtclines[qtcrow].time, fieldval);
1313 		    if (qtc_auto_filltime == 1) {
1314 			fill_qtc_times(fieldval);
1315 		    }
1316 		    break;
1317 		case 1:
1318 		    strcpy(qtcreclist.qtclines[qtcrow].callsign, fieldval);
1319 		    break;
1320 		case 2:
1321 		    strcpy(qtcreclist.qtclines[qtcrow].serial, fieldval);
1322 		    break;
1323 	    }
1324 	    if (curpos > 0) {
1325 		curpos--;
1326 	    }
1327 	    showfield(activefield);
1328 	    if (stridx == 0 && strlen(fieldval) == pos[posidx][2]
1329 		    && activefield <= 32) {	// auto TAB if curr field is QTC time, and len is 4
1330 		curpos = 0;
1331 		activefield++;
1332 		showfield(activefield - 1);
1333 		showfield(activefield);
1334 	    }
1335 	}
1336     }
1337 }
1338 
delete_from_field(int dir)1339 void delete_from_field(int dir) {
1340 
1341     char fieldval[16];
1342     int fi, winrow, qtcrow, stridx;
1343 
1344     fieldval[0] = '\0';
1345 
1346     if (activefield == 0) {
1347 	if (strlen(qtccallsign) > 0) {
1348 	    sprintf(fieldval, "%s", qtccallsign);
1349 	    shift_left(fieldval, dir);
1350 	    g_strlcpy(qtccallsign, fieldval, QTC_CALL_SIZE);
1351 	    qtccallsign[strlen(fieldval)] = '\0';
1352 	    recalc_qtclist();
1353 	    showfield(0);
1354 	}
1355     } else if (activefield == 1) {
1356 	sprintf(fieldval, "%d", qtcreclist.serial);
1357 	if (strlen(fieldval) > 0) {
1358 	    //sprintf(fieldval, "%d", qtcreclist.serial/10);
1359 	    shift_left(fieldval, dir);
1360 	    qtcreclist.serial = atoi(fieldval);
1361 	    showfield(1);
1362 	}
1363     } else if (activefield == 2) {
1364 	sprintf(fieldval, "%d", *qtccount);
1365 	if (strlen(fieldval) > 0) {
1366 	    //sprintf(fieldval, "%d", *qtccount/10);
1367 	    shift_left(fieldval, dir);
1368 	    *qtccount = atoi(fieldval);
1369 	    showfield(2);
1370 	}
1371     } else {
1372 	fi = activefield - 3;
1373 	winrow = (fi / 3) + 3;
1374 	qtcrow = winrow - 3;
1375 	stridx = fi % 3;
1376 	switch (stridx) {
1377 	    case 0:
1378 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].time);
1379 		break;
1380 	    case 1:
1381 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].callsign);
1382 		break;
1383 	    case 2:
1384 		sprintf(fieldval, "%s", qtcreclist.qtclines[qtcrow].serial);
1385 		break;
1386 	}
1387 
1388 	if (strlen(fieldval) > 0) {
1389 	    shift_left(fieldval, dir);
1390 	    fieldval[strlen(fieldval)] = '\0';
1391 	    switch (stridx) {
1392 		case 0:
1393 		    strcpy(qtcreclist.qtclines[qtcrow].time, fieldval);
1394 		    break;
1395 		case 1:
1396 		    strcpy(qtcreclist.qtclines[qtcrow].callsign, fieldval);
1397 		    break;
1398 		case 2:
1399 		    strcpy(qtcreclist.qtclines[qtcrow].serial, fieldval);
1400 		    break;
1401 	    }
1402 	    showfield(activefield);
1403 	}
1404     }
1405 }
1406 
shift_left(char * fieldval,int shift)1407 void shift_left(char *fieldval, int shift) {
1408     int i;
1409 
1410     for (i = strlen(fieldval) - (curpos + shift); i < strlen(fieldval); i++) {
1411 	fieldval[i] = fieldval[i + 1];
1412     }
1413     if (shift == 0) {
1414 	curpos--;
1415     }
1416 }
1417 
show_status(int idx)1418 void show_status(int idx) {
1419 
1420     char flag = ' ';
1421     int i, status = 0;
1422 
1423     status = 0;
1424     if (idx < *qtccount) {
1425 	if (strlen(qtcreclist.qtclines[idx].time) != 4) {
1426 	    status = 1;
1427 	} else {
1428 	    for (i = 0; i < strlen(qtcreclist.qtclines[idx].time); i++) {
1429 		if (qtcreclist.qtclines[idx].time[i] == '?'
1430 			|| ! isdigit(qtcreclist.qtclines[idx].time[i])) {
1431 		    status = 1;
1432 		    break;
1433 		}
1434 	    }
1435 	}
1436 	if (strlen(qtcreclist.qtclines[idx].callsign) < 3) {
1437 	    status = 1;
1438 	} else {
1439 	    for (i = 0; i < strlen(qtcreclist.qtclines[idx].callsign); i++) {
1440 		if (qtcreclist.qtclines[idx].callsign[i] == '?') {
1441 		    status = 1;
1442 		    break;
1443 		}
1444 	    }
1445 	}
1446 	if (strlen(qtcreclist.qtclines[idx].serial) == 0) {
1447 	    status = 1;
1448 	}
1449 	for (i = 0; i < strlen(qtcreclist.qtclines[idx].serial); i++) {
1450 	    if (qtcreclist.qtclines[idx].serial[i] == '?'
1451 		    || ! isdigit(qtcreclist.qtclines[idx].serial[i])) {
1452 		status = 1;
1453 		break;
1454 	    }
1455 	}
1456 	if (status == 1) {
1457 	    qtcreclist.qtclines[idx].status = 1;
1458 	} else if (qtcreclist.qtclines[idx].status !=
1459 		   2) {	// unset incomplete mark if not marked as complete
1460 	    qtcreclist.qtclines[idx].status = 0;
1461 	}
1462 
1463 	switch (qtcreclist.qtclines[idx].status) {
1464 	    case 0:
1465 		flag = ' ';
1466 		break;
1467 	    case 1:
1468 		flag = '?';
1469 		break;
1470 	    case 2:
1471 		flag = '*';
1472 		break;
1473 	}
1474 	if (trxmode == DIGIMODE && qtcreclist.qtclines[idx].status == 0) {
1475 	    flag = '+';
1476 	}
1477 	wattrset(qtcwin, (chtype)(A_NORMAL | COLOR_PAIR(QTCRECVBG)));
1478 	mvwprintw(qtcwin, idx + 3, 30, "%c", flag);
1479     }
1480 }
1481 
number_fields()1482 void number_fields() {
1483     int i;
1484 
1485     wattrset(qtcwin, (chtype)(A_NORMAL | COLOR_PAIR(QTCRECVBG)));
1486     for (i = 0; i < QTC_LINES; i++) {
1487 	mvwprintw(qtcwin, i + 3, 1, "  ");
1488     }
1489     for (i = 0; i < *qtccount; i++) {
1490 	mvwprintw(qtcwin, i + 3, 1, "%2d", i + 1);
1491     }
1492 }
1493 
clear_help_block()1494 void clear_help_block() {
1495     int i;
1496 
1497     wattrset(qtcwin, LINE_INVERTED);
1498     for (i = 1; i < 13; i++) {
1499 	mvwprintw(qtcwin, i, 36, "                                      ");
1500     }
1501 }
1502 
show_help_msg(int msgidx)1503 void show_help_msg(int msgidx) {
1504     int i = 0, j = 0;
1505     char buff[80];
1506     int currqtc;
1507 
1508     clear_help_block();
1509 
1510     wattrset(qtcwin, LINE_CURRINVERTED);
1511     if (qtccurrdirection == RECV) {
1512 	if (trxmode == DIGIMODE && qtccurrdirection == RECV) {
1513 	    currqtc = ((activefield - 3) / 3);
1514 	    if (qtcreclist.qtclines[currqtc].status == 0 &&
1515 		    strlen(qtcreclist.qtclines[currqtc].time) == 4 &&
1516 		    strlen(qtcreclist.qtclines[currqtc].callsign) > 0 &&
1517 		    strlen(qtcreclist.qtclines[currqtc].serial) > 0
1518 	       ) {
1519 		mvwprintw(qtcwin, ++j, 36, "Press ENTER to mark as RCVD");
1520 	    }
1521 	} else {
1522 	    mvwprintw(qtcwin, ++j, 36, help_rec_msgs[msgidx]);
1523 	}
1524     }
1525     if (qtccurrdirection == SEND) {
1526 	if (msgidx > 2 && msgidx < 6) {
1527 	    msgidx = 3;
1528 	}
1529 	mvwprintw(qtcwin, ++j, 36, help_send_msgs[msgidx]);
1530     }
1531     wattrset(qtcwin, LINE_INVERTED);
1532     mvwprintw(qtcwin, ++j, 36, "PgUP/PgDW: QRQ/QRS      CTRL-N: NO QTC");
1533     if (qtccurrdirection == RECV) {
1534 	mvwprintw(qtcwin, ++j, 36, "ENTER: R & next OR AGN  CTRL-L: LATER ");
1535     }
1536     if (qtccurrdirection == SEND) {
1537 	mvwprintw(qtcwin, ++j, 36, "ENTER: send QTC         CTRL-L: LATER ");
1538     }
1539     for (i = 0; i < 12 && j < 12; i++) {
1540 	if (qtccurrdirection == RECV) {
1541 	    if (strlen(qtc_recv_msgs[i]) > 0) {
1542 		g_strlcpy(buff, qtc_recv_msgs[i], sizeof(buff));
1543 		mvwprintw(qtcwin, ++j, 36, "F%-2d: %s", (i + 1), buff);
1544 	    }
1545 	    if (i == 1) {
1546 		mvwprintw(qtcwin, j - 1, 56, "CTRL-F: FILL TIMES");
1547 	    }
1548 	    if (i == 2) {
1549 		mvwprintw(qtcwin, j - 1, 56, "CTRL-R: RECORD");
1550 	    }
1551 	}
1552 	if (qtccurrdirection == SEND) {
1553 	    if (strlen(qtc_send_msgs[i]) > 0) {
1554 		g_strlcpy(buff, qtc_send_msgs[i], sizeof(buff));
1555 		mvwprintw(qtcwin, ++j, 36, "F%-2d: %s", (i + 1), buff);
1556 	    }
1557 	}
1558     }
1559     if (trxmode == DIGIMODE && qtccurrdirection == RECV) {
1560 	mvwprintw(qtcwin, ++j, 36, "CTRL-T: Terminal window");
1561 	mvwprintw(qtcwin, ++j, 36, "CTRL-S: Start capture");
1562 	mvwprintw(qtcwin, ++j, 36, "CTRL-E: End capture");
1563     }
1564 }
1565 
parse_ry_line(char * line)1566 int parse_ry_line(char *line) {
1567     int j, i = 0, t = -1, f;
1568     char lline[40], *token, *wtoken, ttoken[50], tokens[5][15] = {"", "", "", "", ""};	// 5 members, cause possible callsign will AB/CD1EF/P, which will use 3
1569     char *saveptr1, *saveptr2;
1570     char sep[6] = "";
1571     int tactivefield;
1572     static int nr_parsed_line = 0;
1573     int serial_nr = 0;
1574     int maxlength[] = {4, 14, 4};
1575 
1576     if (*qtccount == 0 || qtcreclist.serial == 0) {
1577 	nr_parsed_line = 0;
1578     }
1579     if ((*qtccount > 0 || qtcreclist.serial > 0) && nr_parsed_line == 0) {
1580 	nr_parsed_line = 1;
1581     }
1582 
1583     g_strlcpy(lline, line, sizeof(lline));
1584     tactivefield = activefield;
1585     if (nr_parsed_line == 0) {		// 1st line: SERIAL/NR
1586 	wtoken = strtok_r(lline, " ", &saveptr1);
1587 	while (wtoken != NULL && nr_parsed_line == 0) {
1588 	    serial_nr = 0;
1589 	    strcpy(ttoken, wtoken);
1590 	    sep[0] = '/';
1591 	    sep[1] = '\0';
1592 	    token = strtok_r(ttoken, sep, &saveptr2);
1593 	    t = -1;
1594 	    while (token != NULL && t < 2) {
1595 		t++;
1596 		strcpy(tokens[t], token);
1597 		token = strtok_r(NULL, sep, &saveptr2);
1598 	    }
1599 	    f = 0;
1600 	    for (i = 0; i <= t; i++) {
1601 		f = 1;
1602 		for (j = 0; j < strlen(tokens[i]); j++) {
1603 		    if (! isdigit(tokens[i][j])) {
1604 			f = 0;
1605 		    }
1606 		}
1607 		if (f == 1) {
1608 		    tactivefield = activefield;
1609 		    activefield = i + 1;
1610 		    showfield(tactivefield);
1611 		    for (j = 0; j < strlen(tokens[i]); j++) {
1612 			modify_field(tokens[i][j]);
1613 		    }
1614 		    showfield(activefield);
1615 		    serial_nr++;
1616 		}
1617 	    }
1618 	    if (serial_nr == 2) {
1619 		nr_parsed_line++;
1620 	    }
1621 	    wtoken = strtok_r(NULL, " ", &saveptr1);
1622 	}
1623     } else {
1624 	strcpy(sep, "/;-: ");
1625 	token = strtok(lline, sep);
1626 	while (token != NULL && t < 4) {
1627 	    t++;
1628 	    strcpy(tokens[t], token);
1629 	    token = strtok(NULL, sep);
1630 	}
1631 
1632 	while (t > 2) {
1633 	    strcat(tokens[1], "/");
1634 	    strcat(tokens[1], tokens[2]);
1635 	    strcpy(tokens[t - 1], tokens[t]);
1636 	    tokens[t][0] = '\0';
1637 	    t--;
1638 	}
1639 
1640 	for (i = 0; i <= t; i++) {
1641 	    f = 1;
1642 	    for (j = 0; j < strlen(tokens[i]); j++) {
1643 		if ((i == 0 || i == 2) && ! isdigit(tokens[i][j])) {
1644 		    tokens[i][j] = '?';
1645 		}
1646 		if (i == 1 && (!isalnum(tokens[i][j]) && tokens[i][j] != '/')) {
1647 		    tokens[i][j] = '?';
1648 		}
1649 	    }
1650 	    if (strlen(tokens[i]) > maxlength[i]) {
1651 		tokens[i][maxlength[i]] = '\0';
1652 	    }
1653 	    if (f == 1) {
1654 		tactivefield = activefield;
1655 		activefield = (nr_parsed_line * 3) + i;
1656 		showfield(tactivefield);
1657 		for (j = 0; j < strlen(tokens[i]); j++) {
1658 		    modify_field(tokens[i][j]);
1659 		}
1660 		showfield(activefield);
1661 	    }
1662 	}
1663 	for (i = ((t > 0) ? t : 0); i < 2; i++) {
1664 	    tactivefield = activefield;
1665 	    activefield = (nr_parsed_line * 3) + i;
1666 	    showfield(tactivefield);
1667 	    modify_field('?');
1668 	    showfield(activefield);
1669 	}
1670 	nr_parsed_line++;
1671 	qtc_ry_copied++;
1672     }
1673     tactivefield = activefield;
1674 
1675     return tactivefield;
1676 }
1677 
1678 /* print one line with its status */
print_rtty_line(t_qtc_ry_line qtc_ry_line,int row)1679 int print_rtty_line(t_qtc_ry_line qtc_ry_line, int row) {
1680     char currline[50];
1681 
1682     sprintf(currline, "%-38s", qtc_ry_line.content);
1683     currline[38] = '\0';
1684     if (qtc_ry_line.attr == 1) {
1685 	currline[36] = ' ';
1686 	currline[37] = '*';
1687     }
1688     mvwprintw(ry_win, row, 1, "%-38s", currline);
1689     return 0;
1690 }
1691 
1692 /* RTTY terminal to helps to capture the RTTY content */
show_rtty_lines()1693 void show_rtty_lines() {
1694     extern int miniterm;
1695 
1696     char boxhead[38];
1697     int prevline;
1698     char currline[50] = "", firstline[50] = "";
1699     int x, j;
1700     static int actline = 1;
1701     int oactivefield, tactivefield;
1702 
1703     oactivefield = activefield;
1704     tactivefield = activefield;
1705 
1706     show_panel(ry_panel);
1707     top_panel(ry_panel);
1708     werase(ry_win);
1709     show_panel(ry_help_panel);
1710     top_panel(ry_help_panel);
1711     werase(ry_help_win);
1712 
1713     sprintf(boxhead, "HELP");
1714     wnicebox(ry_help_win, 0, 0, 3, 73, "HELP");
1715     wbkgd(ry_help_win, (chtype)(A_NORMAL | COLOR_PAIR(QTCRECVWINBG)));
1716     wattrset(ry_help_win, LINE_INVERTED);
1717     //                           "1234567890123456789012345678901234567890123456789012345678901234567890123"
1718     mvwprintw(ry_help_win, 1, 1,
1719 	      "CTRL-R: Reset lines  -  CTRL-S: Start capture  -  CTRL-E: End capture    ");
1720     mvwprintw(ry_help_win, 2, 1,
1721 	      "ENTER: add current line to QTC  -  Up/Down: move                         ");
1722     mvwprintw(ry_help_win, 3, 1,
1723 	      "ESC: hide RTTY window                                                    ");
1724 
1725     strcpy(boxhead, "RTTY");
1726     wnicebox(ry_win, 0, 0, 12, 38, boxhead);
1727     wattrset(ry_win, LINE_NORMAL);
1728     for (j = 1; j < 13; j++) {
1729 	mvwprintw(ry_win, j, 1, "                                      ");
1730     }
1731     refreshp();
1732 
1733     if (qtc_ry_capture == 1) {
1734 	mvwprintw(qtcwin, 2, 11, "CAPTURE ON ");
1735     } else {
1736 	mvwprintw(qtcwin, 2, 11, "CAPTURE OFF");
1737     }
1738 
1739     x = -1; j = 1;
1740     prevline = -1;
1741     curs_set(0);
1742     while (x != ESCAPE) {
1743 
1744 	while (x < 1) {
1745 
1746 	    usleep(1000);
1747 	    time_update();
1748 
1749 	    if (miniterm == 1 && trxmode == DIGIMODE && digikeyer != NO_KEYER) {
1750 		show_rtty();
1751 	    }
1752 
1753 	    if ((qtc_ry_currline < 11 && prevline != qtc_ry_currline - 1)
1754 		    || qtc_ry_currline == 11) {
1755 		if (actline > 1 && strcmp(firstline, qtc_ry_lines[0].content) != 0) {
1756 		    actline--;
1757 		    strcpy(firstline, qtc_ry_lines[0].content);
1758 		}
1759 		if (actline == 1 && qtc_ry_currline > 0) {
1760 		    strcpy(firstline, qtc_ry_lines[0].content);
1761 		}
1762 		for (j = 0; j < qtc_ry_currline; j++) {
1763 		    if (j + 1 == actline) {
1764 			wattrset(ry_win, LINE_CURRNORMAL);
1765 		    }
1766 		    print_rtty_line(qtc_ry_lines[j], j + 1);
1767 		    wattrset(ry_win, LINE_NORMAL);
1768 		}
1769 		prevline = qtc_ry_currline - 1;
1770 	    }
1771 
1772 	    strncpy(currline, qtc_ry_lines[qtc_ry_currline].content, 38);
1773 	    currline[39] = '\0';
1774 	    mvwprintw(ry_win, qtc_ry_currline + 1, 1, "%-38s", currline);
1775 
1776 	    refreshp();
1777 	    x = key_poll();
1778 	}
1779 
1780 	switch (x) {
1781 
1782 	    // Up arrow
1783 	    case KEY_UP:
1784 		wattrset(ry_win, LINE_NORMAL);
1785 		print_rtty_line(qtc_ry_lines[actline - 1], actline);
1786 		if (actline > 1) {
1787 		    actline--;
1788 		} else {
1789 		    if (qtc_ry_currline > 0) {
1790 			actline = qtc_ry_currline;
1791 		    }
1792 		}
1793 		wattrset(ry_win, LINE_CURRNORMAL);
1794 		print_rtty_line(qtc_ry_lines[actline - 1], actline);
1795 		wattrset(ry_win, LINE_NORMAL);
1796 		break;
1797 
1798 	    // Down arrow
1799 	    case KEY_DOWN:
1800 		wattrset(ry_win, LINE_NORMAL);
1801 		print_rtty_line(qtc_ry_lines[actline - 1], actline);
1802 		if (actline < qtc_ry_currline) {
1803 		    actline++;
1804 		} else {
1805 		    actline = 1;
1806 		}
1807 		wattrset(ry_win, LINE_CURRNORMAL);
1808 		print_rtty_line(qtc_ry_lines[actline - 1], actline);
1809 		wattrset(ry_win, LINE_NORMAL);
1810 		break;
1811 
1812 	    // Ctrl-R (^R)
1813 	    case CTRL_R:
1814 		for (j = 0; j < 12; j++) {
1815 		    qtc_ry_lines[j].content[0] = '\0';
1816 		    qtc_ry_lines[j].attr = 0;
1817 		    mvwprintw(ry_win, (j + 1), 1, "                                      ");
1818 		}
1819 		prevline = -1;
1820 		actline = 1;
1821 		qtc_ry_currline = 0;
1822 		qtc_ry_copied = 0;
1823 		break;
1824 
1825 	    // Ctrl-S (^S), start capture
1826 	    case CTRL_S:
1827 		qtc_ry_capture = 1;
1828 		mvwprintw(qtcwin, 2, 11, "CAPTURE ON ");
1829 		break;
1830 
1831 	    // Ctrl-E (^E), end capture
1832 	    case CTRL_E:
1833 		qtc_ry_capture = 0;
1834 		mvwprintw(qtcwin, 2, 11, "CAPTURE OFF");
1835 		break;
1836 
1837 	    // <Enter>, add to qtc
1838 	    case LINEFEED:
1839 		if (qtc_ry_lines[actline - 1].attr == 0) {
1840 		    parse_ry_line(qtc_ry_lines[actline - 1].content);
1841 		    qtc_ry_lines[actline - 1].attr = 1;
1842 		}
1843 		wattrset(ry_win, LINE_CURRNORMAL);
1844 		print_rtty_line(qtc_ry_lines[actline - 1], actline);
1845 		wattrset(ry_win, LINE_NORMAL);
1846 		break;
1847 	}
1848 	refreshp();
1849 	if (x != ESCAPE) {
1850 	    x = -1;
1851 	}
1852 	if (*qtccount > 0 && qtc_ry_copied == qtcreclist.count) {
1853 	    qtc_ry_capture = 0;
1854 	    mvwprintw(qtcwin, 2, 11, "CAPTURE OFF");
1855 	}
1856     }
1857     hide_panel(ry_panel);
1858     hide_panel(ry_help_panel);
1859 
1860     curs_set(1);
1861     tactivefield = activefield;
1862     activefield = oactivefield;
1863     showfield(tactivefield);
1864     showfield(oactivefield);
1865 }
1866 
put_qtc()1867 void put_qtc() {
1868 
1869     char qtcdirstring[3][10] = {"", "Received", "Sent"};
1870 
1871     wattrset(qtcwin, LINE_NORMAL);
1872     if (qtc_temp_obj->capable == -1 && qtc_temp_obj->total == 0) {
1873 	mvwprintw(qtcwin, 1, 19, "FLAG: NO QTC");
1874     } else {
1875 	mvwprintw(qtcwin, 1, 19, "%s %2d QTC", qtcdirstring[qtccurrdirection],
1876 		  qtc_temp_obj->total);
1877     }
1878 
1879 }
1880 
replace_spaces(char * src,char * tempc)1881 void replace_spaces(char *src, char *tempc) {
1882     int tsp, tdp;
1883 
1884     tsp = 0;
1885     tdp = 0;
1886     g_strstrip(src);
1887     while (src[tsp] != '\0') {
1888 	if (src[tsp] != ' ') {
1889 	    tempc[tdp] = src[tsp];
1890 	    tdp++;
1891 	} else {
1892 	    if (trxmode == DIGIMODE) {
1893 		tempc[tdp] = '-';
1894 	    } else {
1895 		tempc[tdp] = ' ';
1896 	    }
1897 	    tdp++;
1898 	    while (src[tsp + 1] == ' ' || src[tsp + 1] == '-') {
1899 		tsp++;
1900 	    }
1901 	}
1902 	tsp++;
1903     }
1904     tempc[tdp] = '\n';
1905     tdp++;
1906     tempc[tdp] = '\0';
1907 }
1908 
show_sendto_lines()1909 void show_sendto_lines() {
1910     int i;
1911 
1912     wattrset(qtcwin, LINE_INVERTED);
1913     for (i = 0; i < QTC_LINES; i++) {
1914 	mvwprintw(qtcwin, i + 3, 1, "                                 ");
1915     }
1916 
1917     wattrset(qtcwin, LINE_NORMAL);
1918     for (i = 0; i < qtclist.count; i++) {
1919 	mvwprintw(qtcwin, i + 3, 4, "%s", qtclist.qtclines[i].qtc);
1920 	if (qtclist.qtclines[i].sent == 1) {
1921 	    mvwprintw(qtcwin, i + 3, 30, "*");
1922 	}
1923     }
1924 
1925     wattrset(qtcwin, LINE_NORMAL);
1926     for (i = qtclist.count; i < QTC_LINES; i++) {
1927 	mvwprintw(qtcwin, i + 3, 4, "                        ");
1928     }
1929     number_fields();
1930 }
1931 
recalc_qtclist()1932 void recalc_qtclist() {
1933     if (qtccurrdirection == SEND) {
1934 	if (strlen(qtccallsign) > 0 && strcmp(qtccallsign, prevqtccall) != 0) {
1935 	    qtc_temp_obj = qtc_get(qtccallsign);
1936 	    *qtccount = genqtclist(qtccallsign, (10 - (qtc_temp_obj->total)));
1937 	    show_sendto_lines();
1938 	    showfield(2);
1939 	    put_qtc();
1940 	}
1941     }
1942     g_strlcpy(prevqtccall, qtccallsign, sizeof(prevqtccall));
1943 }
1944