Problem
The terminal emulation software escape key sequence does not match the UNIX TERMINFO escape sequence.
How do you identify the escape key sequence to use in a TERMINFO file for a particular key depression like F2 or shift F2 etc…
Resolution
Here is a program scanwinput.c to display the escape sequences received by a UNIX system, which can be used to update your TERMINFO files.
Getting this output is a good step to solving the complex issue of terminal configuration on UNIX platforms.
OUTPUT from program when pressing F2 key
lines <25> columns <70> termname
longname xterm terminal emulator (X Window System)
Enter a string or key sequence like ctrl-f4 to see hex values or q exit
<^[OQ >
You Entered : ^[OQ
You entered in hex : 1b4f51
Press any key to continue :
scanwinput.c will show all available options for the TERMINFO file in use.
OUTPUT scanwinput.c option d
str ked key_eos = ABSENT_STRING
str kf0 key_f0 = ABSENT_STRING
str kf1 key_f1 = \\EOP
str kf10 key_f10 = \\E[21~
str kf2 key_f2 = \\EOQ
str kf3 key_f3 = \\EOR
The above shows that kf2 is ”\\E” escape x’1b’ and “OQ” which is what we got when we pressed the F2 key so good match.
We can expand a mftic generated TERMINFO file using mfinfocmp to see the TERMINFO source
OUTPUT mfinfocmp
mfinfocmp -1 | grep kf2=
kf2=\\EOQ,
Change the output from mfinfocmp and put it back in the TERMINFO database using mftic.
The c source code
To download the c source code, click the link and save as < scanwinput.c >
scanwinput.c
/* to see what ncurses can do see */
/* http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html */
/* http://frank.harvard.edu/~coldwell/ncurses/ncurses-intro.html this one looks good first has examples */
/* now this is the mecca of ncurses sites the curses test site */
/* http://stuff.mit.edu/afs/sipb/project/ncurses/cron-working/ncurses/test/ */
#include <stdio.h>
#if defined(_AIX)
#include <curses.h>
#define ABSENT_BOOLEAN ((signed char)-1) /* 255 */
#define ABSENT_NUMERIC (-1)
#define ABSENT_STRING (char *)0
#define CANCELLED_STRING (char *)(-1)
#else
#include <ncurses/ncurses.h>
#include <ncurses/term.h>
#include <ncurses/tic.h>
#endif
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#define STR1LEN 15
#define STR2LEN 30
#define FCAPDISP(type, str1, str2) "%s %-*s %-*s = ", #type, STR1LEN, str1, STR2LEN, str2
int main() {
WINDOW *_window = initscr();
char mesg[] =
"Enter a string or key sequnce like ctrl-f4 to see hex values or q exit"; /* message to be appeared on the screen */
char mesg1[] =
"< >"; /* place to get string data escape sequences */
char str[strlen(mesg1) - 2];
int row, col; /* to store the number of rows and */
/* the number of colums of the screen */
getmaxyx(_window, row, col); /* get the number of rows and columns */
do {
#if defined(_AIX)
mvprintw(row/4,(col-strlen(mesg))/2,
"lines <%s> columns <%s> termname <%s>", termdef(2, 'l'), termdef(2, 'c'), termdef(2, 't'));
#else
mvprintw(row / 4, (col - strlen(mesg)) / 2,
"lines <%d> columns <%d> termname <%s>", row, col, termname());
#endif
mvprintw((row / 4) 1, (col - strlen(mesg)) / 2, "longname %s",
longname());
mvprintw(row / 2, (col - strlen(mesg)) / 2, "%s", mesg); /* print the message at the center of the screen */
mvprintw(row / 2 1, (col - strlen(mesg)) / 2, "%s", mesg1);
move(row / 2 1, ((col - strlen(mesg)) / 2) 1);
refresh();
getstr(str);
if (str[0] == 'q')
break;
mvprintw(row / 2 2, (col - strlen(mesg)) / 2,
"You Entered : %s", str);
mvprintw(row / 2 3, (col - strlen(mesg)) / 2,
"You entered in hex : ");
int n;
for (n = 0; str[ n ] != '\\0'; n )
printw("x", (unsigned char) str[ n ]);
mvprintw(row / 2 4, (col - strlen(mesg)) / 2,
"Press any key to continue : ");
refresh();
getch();
clear();
} while (true);
mvprintw(row - 2, 0, "Press any key to exit d to see terminfo : ");
refresh();
char c = getch();
endwin();
/* using stuff from mecca site above dump terminfo stuff */
if (c == 'd') {
printf("mftic and mfinfocmp must be used for TERMINFOS being used by MF COBOL\\n");
printf("mftic puts key definitions in different places than tic so must use mftic\\n");
printf("mftic uses old ncurses libraries so definitions need to be compiled and extracted\\n");
printf("using mftic and mfinfocomp, enough said.\\n");
printf("\\n");
#if defined(_AIX)
printf("%s|%s\\n", termdef(2, 't'), longname());
#else
printf("%s|%s\\n", termname(), longname());
#endif
fflush(stdout);
unsigned n;
char *cap;
char *capf;
const char *str;
int num;
for (n = 0;; n) {
cap = boolnames[ n ];
capf = boolfnames[ n ];
if (cap == 0)
break;
num = tigetflag(cap);
printf(FCAPDISP(flg, cap, capf));
if (num == ABSENT_BOOLEAN) {
printf(" ABSENT_BOOLEAN\\n");
} else {
printf(" %s\\n", num ? "true" : "false");
}
fflush(stdout);
}
for (n = 0;; n) {
cap = numnames[ n ];
capf = numfnames[ n ];
if (cap == 0)
break;
printf(FCAPDISP(num, cap, capf));
num = tigetnum(cap);
if (num == ABSENT_NUMERIC) {
printf(" ABSENT_NUMERIC\\n");
} else {
printf(" %d\\n", num);
}
fflush(stdout);
}
for (n = 0;; n) {
cap = strnames[ n ];
capf = strfnames[ n ];
if (cap == 0)
break;
printf(FCAPDISP(str, cap, capf));
str = tigetstr(cap);
if (str == CANCELLED_STRING) {
str = "CANCELLED_STRING";
} else if (str == ABSENT_STRING) {
str = "ABSENT_STRING";
}
while (*str != 0) {
int ch = (int) *str ;
switch (ch) {
case '\\177':
fputs("^?", stdout);
break;
case '\\033':
fputs("\\\\E", stdout);
break;
case '\\b':
fputs("\\\\b", stdout);
break;
case '\\f':
fputs("\\\\f", stdout);
break;
case '\\n':
fputs("\\\\n", stdout);
break;
case '\\r':
fputs("\\\\r", stdout);
break;
case ' ':
fputs("\\\\s", stdout);
break;
case '\\t':
fputs("\\\\t", stdout);
break;
case '^':
fputs("\\\\^", stdout);
break;
case ':':
fputs("\\\\072", stdout);
break;
case '\\\\':
fputs("\\\\\\\\", stdout);
break;
default:
if (isgraph(ch))
fputc(ch, stdout);
else if (ch < 32)
printf("^%c", ch '@');
else
printf("\\\\o", ch);
break;
}
}
printf("\\n");
fflush(stdout);
}
}
return 0;
}
To compile on UNIX
cob -xv scanwinput.c -lcurses -o scanwinput
This is just a starting point for solving TERMINFO problems.
#COBOL
#UNIXTERMINFOCESCAPE-SEQUENCETERMINAL