/* * 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); }