/*
* Tlf - contest logging program for amateur radio operators
* Copyright (C) 2015 Thomas Beierlein
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* User Interface helpers for ncurses based user interface */
#include
#include
#include
#include
static int getkey(int wait);
static int onechar(void);
void stoptx(void)
{
printw("TX stopped.\n");
refresh();
}
/** key_get wait for next key from terminal
*
*/
int key_get()
{
return getkey(1);
}
/** key_poll return next key from terminal if there is one
*
*/
int key_poll()
{
return getkey(0);
}
/* helper function to set 'nodelay' mode according to 'wait'
* parameter and then ask for the next character
* leaves 'nodelay' afterwards always as FALSE (meaning: wait for
* character
*/
static int getkey(int wait)
{
int x = 0;
nodelay(stdscr, wait ? FALSE : TRUE);
x = onechar();
nodelay(stdscr, FALSE);
return x;
}
/* New onechar() that takes advantage of Ncurses keypad mode and processes
* certain escaped keys and assigns them to Ncurses values known by
* keyname(). Also catches Escape and processes it immediately as well
* as calling stoptx() for minimal delay.
*/
static int onechar(void)
{
int x = 0;
int trash = 0;
x = getch();
/* Replace Ctl-H and Backspace with KEY_BACKSPACE */
if (x == 8 || x == 127)
x = KEY_BACKSPACE;
if (x == 27) {
nodelay(stdscr, TRUE);
x = getch();
/* Escape pressed, not an escaped key. */
if (x == ERR) {
stoptx();
return x = 27;
} else if (x != 91) {
switch (x) {
case 32 ... 57: // Alt-Space to Alt-9, 160 - 185
case 97 ... 122: // Alt-a to alt-z, 225 - 250
x += 128;
break;
/* Not all terminals support Ctl-Shift-ch so
* treat them as Alt-ch
*/
case 65 ... 78: // alt-A to alt-N, 225 - 238
case 80 ... 90: // alt-P to alt-Z, 240 - 250
x += 160;
break;
case 79: {
x = getch();
/* Catch Alt-O */
if (x == ERR) {
x = 239;
break;
}
/* Key codes for Shift-F1 to Shift-F4 in Xfce terminal. */
if (x == 49) {
x = getch();
if (x == 59) {
x = getch();
if (x == 50) {
x = getch();
switch (x) {
case 80: {
x = KEY_F(13);
break;
}
case 81: {
x = KEY_F(14);
break;
}
case 82: {
x = KEY_F(15);
break;
}
case 83: {
x = KEY_F(16);
break;
}
}
}
}
}
}
}
nodelay(stdscr, FALSE);
} else {
nodelay(stdscr, FALSE);
x = getch(); /* Get next code after 91 */
switch (x) {
/* Key codes for this section:
* 27 91 49 126 Home
* 27 91 52 126 End
*
* Needed for the keypad Pg-Up and Pg-Dn keys in Xfce terminal.
*/
case 49: {
x = getch();
if (x == 126) {
x = KEY_HOME;
break;
}
}
case 52: {
x = KEY_END;
trash = getch();
break;
}
}
}
}
/* It seems Xterm treats Alt-Space through Alt-9 with a prefix
* character of 194 followed by 160 through 185.
*/
if (x == 194) {
nodelay(stdscr, TRUE);
trash = getch();
if (trash == ERR)
return x;
x = trash;
// Alt-Space to Alt-9
if (x >= 160 && x <= 185) {
nodelay(stdscr, FALSE);
return x;
}
}
/* It seems Xterm treats Alt-a to Alt-z with a prefix
* character of 195 followed by 161-186 (a-z) or
* 129-154 (A-Z).
*/
if (x == 195) {
nodelay(stdscr, TRUE);
trash = getch();
if (trash == ERR)
return x;
x = trash;
switch (x) {
case 161 ... 186: // Alt-a to Alt-z 225 - 250
x += 64;
break;
case 129 ... 154: // Alt-A to Alt-Z 225 - 250
x += 96;
break;
}
nodelay(stdscr, FALSE);
}
return x;
}
static struct termios oldt, newt;
int main(void)
{
int x;
SCREEN *mainscreen;
/* modify stdin terminals attributes to allow Ctrl-Q/S key recognition */
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_iflag &= ~(IXON);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
/* activate ncurses terminal control */
if ((mainscreen = newterm(NULL, stdout, stdin)) == NULL) {
perror("initscr");
printf("\nSorry, wrong terminal type !!!!! \n"
"Try a linux text terminal or set TERM=linux !!!\n");
sleep(2);
exit(EXIT_FAILURE);
}
noecho();
crmode();
keypad(stdscr, TRUE); // Have Ncurses process most special keys
scrollok(stdscr, TRUE);
set_term(mainscreen);
/* Speed up Escape processing, setting the Ncurses Escape
* dealy to 25 mS. Should be enough time to catch escaped
* key codes.
*/
set_escdelay(25);
printw("Tests escaped keys used in Tlf. Press Ctl-D to exit.\n\n");
printw("Escape delay time is: %d mS\n", get_escdelay());
/* Break out with Ctl-D. */
while (x != 4) {
x = key_get();
printw("Ordinal: %d\t\tName: %s\n", x, keyname(x));
refresh();
}
endwin();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
exit(EXIT_SUCCESS);
}