cks@white.toronto.edu (Chris Siebenmann) (06/27/89)
Recently I became disenchanted with how GNU Emacs bound X11 function keys (because of things such as using a hardcoded list that differed on Suns vs. everyone else, missing various useful keys like the keyboard function keys), and decided to find a better scheme. My current technique is to generate the sequence ESC [ <keysym name or hex number> ~ (eg ESC [ F 1 ~ for F1) (hex numbers are only generated if the keysym has no name, eg the Remove key on DEC and GraphOn keyboards). The new code is smaller, simpler, more predictable, and lets you bind any key that your keyboard produces; it uses the same names for keys as all other X11 programs do. Its only disadvantage is that it isn't compatable with the old scheme -- considering how .. ah .. baroque the old scheme was I don't consider this much of a disadvantage. If you want to do this too, apply the following patch to src/x11term.c: *** x11term.c.orig Fri Feb 24 16:44:00 1989 --- x11term.c Tue Jun 20 16:50:11 1989 *************** *** 1055,1211 * from elisp. */ - #ifdef sun - char *stringFuncVal(keycode) - KeySym keycode; - { - switch (keycode) { - case XK_L1: - return("192"); - case XK_L2: - return("193"); - case XK_L3: - return("194"); - case XK_L4: - return("195"); - case XK_L5: - return("196"); - case XK_L6: - return("197"); - case XK_L7: - return("198"); - case XK_L8: - return("199"); - case XK_L9: - return("200"); - case XK_L10: - return("201"); - - case XK_R1: - return("208"); - case XK_R2: - return("209"); - case XK_R3: - return("210"); - case XK_R4: - return("211"); - case XK_R5: - return("212"); - case XK_R6: - return("213"); - case XK_R7: - return("214"); - case XK_R8: - return("215"); - case XK_R9: - return("216"); - case XK_R10: - return("217"); - case XK_R11: - return("218"); - case XK_R12: - return("219"); - case XK_R13: - return("220"); - case XK_R14: - return("221"); - case XK_R15: - return("222"); - - case XK_Break: /* Sun3 "Alternate" key */ - return("223"); - - case XK_F1: - return("224"); - case XK_F2: - return("225"); - case XK_F3: - return("226"); - case XK_F4: - return("227"); - case XK_F5: - return("228"); - case XK_F6: - return("229"); - case XK_F7: - return("230"); - case XK_F8: - return("231"); - case XK_F9: - return("232"); - - default: - return("-1"); - } - } - #else - char *stringFuncVal(keycode) - KeySym keycode; - { - switch (keycode) { - case XK_F1: - return("11"); - case XK_F2: - return("12"); - case XK_F3: - return("13"); - case XK_F4: - return("14"); - case XK_F5: - return("15"); - case XK_F6: - return("17"); - case XK_F7: - return("18"); - case XK_F8: - return("19"); - case XK_F9: - return("20"); - case XK_F10: - return("21"); - case XK_F11: - return("23"); - case XK_F12: - return("24"); - case XK_F13: - return("25"); - case XK_F14: - return("26"); - case XK_F15: - return("28"); - case XK_Help: - return("28"); - case XK_F16: - return("29"); - case XK_Menu: - return("29"); - case XK_F17: - return("31"); - case XK_F18: - return("32"); - case XK_F19: - return("33"); - case XK_F20: - return("34"); - - case XK_Find : - return("1"); - case XK_Insert: - return("2"); - case XK_Delete: - return("3"); - case XK_Select: - return("4"); - case XK_Prior: - return("5"); - case XK_Next: - return("6"); - default: - return("-1"); - } - } - #endif /* not sun */ - internal_socket_read(bufp, numchars) register unsigned char *bufp; register int numchars; --- 1055,1060 ----- * from elisp. */ internal_socket_read(bufp, numchars) register unsigned char *bufp; register int numchars; *************** *** 1324,1344 nbytes = XLookupString (&event, mapping_buf, 20, &keysym, &status); ! /* Someday this will be unnecessary as we will ! be able to use XRebindKeysym so XLookupString ! will have already given us the string we want. */ ! if (IsFunctionKey(keysym) || ! IsMiscFunctionKey(keysym)) { ! strcpy(mapping_buf,"["); ! strcat(mapping_buf,stringFuncVal(keysym)); ! #ifdef sun ! strcat(mapping_buf,"z"); ! #else ! strcat(mapping_buf,"~"); ! #endif /* sun */ ! nbytes = strlen(mapping_buf); ! } ! else { switch (keysym) { case XK_Left: strcpy(mapping_buf,"\002"); --- 1173,1189 ----- nbytes = XLookupString (&event, mapping_buf, 20, &keysym, &status); ! /* If XLookupString knows a string for this buffer, or the key ! doesn't have a symbol, or the key is a modifier key (like shift) ! we take it as-is. Otherwise, we take what XKeysymToString gives ! us with a ESC-[ on front and a ~ on the end. If XKeysymToString ! gives us nothing, we use the hex code instead. */ ! if (nbytes == 0 && keysym != NoSymbol && !IsModifierKey(keysym)) { ! char *ksname; ! ! #ifndef NOCURSORHACK ! /* This shouldn't really be needed, but the great god Backwards ! Compatability dictates that we do this. */ switch (keysym) { case XK_Left: strcpy(mapping_buf,"\002"); *************** *** 1356,1361 strcpy(mapping_buf,"\016"); nbytes = 1; break; } } if (nbytes) { --- 1201,1218 ----- strcpy(mapping_buf,"\016"); nbytes = 1; break; + default: + #endif + ksname = XKeysymToString (keysym); + if (ksname == NULL) + sprintf(mapping_buf, "[%x~", keysym); + else { + strcpy(mapping_buf, "["); + strcat(mapping_buf, ksname); + strcat(mapping_buf, "~"); /* none of this sun oddity BS */ + } + nbytes = strlen(mapping_buf); + #ifndef NOCURSORHACK } #endif } *************** *** 1357,1362 nbytes = 1; break; } } if (nbytes) { if (event.xkey.state & Mod1Mask) --- 1214,1220 ----- nbytes = strlen(mapping_buf); #ifndef NOCURSORHACK } + #endif } if (nbytes) { if (event.xkey.state & Mod1Mask) -- "I shall clasp my hands together and bow to the corners of the world." Number Ten Ox, "Bridge of Birds" Chris Siebenmann ...!utgpu!{ncrcan,ontmoh!moore}!ziebmef!cks cks@white.toronto.edu or ...!utgpu!{,csri!}cks
cks@white.toronto.edu (Chris Siebenmann) (06/28/89)
Oops, as they say. It has been pointed out to me that the patches I posted had explicit escape characters in them which got swallowed up by our news software. Here's a corrected patch; apply this one INSTEAD of the previous patch. *** x11term.c.orig Fri Feb 24 16:44:00 1989 --- x11term.c Wed Jun 28 14:03:00 1989 *************** *** 1055,1211 * from elisp. */ - #ifdef sun - char *stringFuncVal(keycode) - KeySym keycode; - { - switch (keycode) { - case XK_L1: - return("192"); - case XK_L2: - return("193"); - case XK_L3: - return("194"); - case XK_L4: - return("195"); - case XK_L5: - return("196"); - case XK_L6: - return("197"); - case XK_L7: - return("198"); - case XK_L8: - return("199"); - case XK_L9: - return("200"); - case XK_L10: - return("201"); - - case XK_R1: - return("208"); - case XK_R2: - return("209"); - case XK_R3: - return("210"); - case XK_R4: - return("211"); - case XK_R5: - return("212"); - case XK_R6: - return("213"); - case XK_R7: - return("214"); - case XK_R8: - return("215"); - case XK_R9: - return("216"); - case XK_R10: - return("217"); - case XK_R11: - return("218"); - case XK_R12: - return("219"); - case XK_R13: - return("220"); - case XK_R14: - return("221"); - case XK_R15: - return("222"); - - case XK_Break: /* Sun3 "Alternate" key */ - return("223"); - - case XK_F1: - return("224"); - case XK_F2: - return("225"); - case XK_F3: - return("226"); - case XK_F4: - return("227"); - case XK_F5: - return("228"); - case XK_F6: - return("229"); - case XK_F7: - return("230"); - case XK_F8: - return("231"); - case XK_F9: - return("232"); - - default: - return("-1"); - } - } - #else - char *stringFuncVal(keycode) - KeySym keycode; - { - switch (keycode) { - case XK_F1: - return("11"); - case XK_F2: - return("12"); - case XK_F3: - return("13"); - case XK_F4: - return("14"); - case XK_F5: - return("15"); - case XK_F6: - return("17"); - case XK_F7: - return("18"); - case XK_F8: - return("19"); - case XK_F9: - return("20"); - case XK_F10: - return("21"); - case XK_F11: - return("23"); - case XK_F12: - return("24"); - case XK_F13: - return("25"); - case XK_F14: - return("26"); - case XK_F15: - return("28"); - case XK_Help: - return("28"); - case XK_F16: - return("29"); - case XK_Menu: - return("29"); - case XK_F17: - return("31"); - case XK_F18: - return("32"); - case XK_F19: - return("33"); - case XK_F20: - return("34"); - - case XK_Find : - return("1"); - case XK_Insert: - return("2"); - case XK_Delete: - return("3"); - case XK_Select: - return("4"); - case XK_Prior: - return("5"); - case XK_Next: - return("6"); - default: - return("-1"); - } - } - #endif /* not sun */ - internal_socket_read(bufp, numchars) register unsigned char *bufp; register int numchars; --- 1055,1060 ----- * from elisp. */ internal_socket_read(bufp, numchars) register unsigned char *bufp; register int numchars; *************** *** 1324,1344 nbytes = XLookupString (&event, mapping_buf, 20, &keysym, &status); ! /* Someday this will be unnecessary as we will ! be able to use XRebindKeysym so XLookupString ! will have already given us the string we want. */ ! if (IsFunctionKey(keysym) || ! IsMiscFunctionKey(keysym)) { ! strcpy(mapping_buf,"["); ! strcat(mapping_buf,stringFuncVal(keysym)); ! #ifdef sun ! strcat(mapping_buf,"z"); ! #else ! strcat(mapping_buf,"~"); ! #endif /* sun */ ! nbytes = strlen(mapping_buf); ! } ! else { switch (keysym) { case XK_Left: strcpy(mapping_buf,"\002"); --- 1173,1189 ----- nbytes = XLookupString (&event, mapping_buf, 20, &keysym, &status); ! /* If XLookupString knows a string for this buffer, or the key ! doesn't have a symbol, or the key is a modifier key (like shift) ! we take it as-is. Otherwise, we take what XKeysymToString gives ! us with a ESC-[ on front and a ~ on the end. If XKeysymToString ! gives us nothing, we use the hex code instead. */ ! if (nbytes == 0 && keysym != NoSymbol && !IsModifierKey(keysym)) { ! char *ksname; ! ! #ifndef NOCURSORHACK ! /* This shouldn't really be needed, but the great god Backwards ! Compatability dictates that we do this. */ switch (keysym) { case XK_Left: strcpy(mapping_buf,"\002"); *************** *** 1356,1361 strcpy(mapping_buf,"\016"); nbytes = 1; break; } } if (nbytes) { --- 1201,1218 ----- strcpy(mapping_buf,"\016"); nbytes = 1; break; + default: + #endif + ksname = XKeysymToString (keysym); + if (ksname == NULL) + sprintf(mapping_buf, "\033[%x~", keysym); + else { + strcpy(mapping_buf, "\033["); + strcat(mapping_buf, ksname); + strcat(mapping_buf, "~"); /* none of this sun oddity BS */ + } + nbytes = strlen(mapping_buf); + #ifndef NOCURSORHACK } #endif } *************** *** 1357,1362 nbytes = 1; break; } } if (nbytes) { if (event.xkey.state & Mod1Mask) --- 1214,1220 ----- nbytes = strlen(mapping_buf); #ifndef NOCURSORHACK } + #endif } if (nbytes) { if (event.xkey.state & Mod1Mask) -- "I shall clasp my hands together and bow to the corners of the world." Number Ten Ox, "Bridge of Birds" Chris Siebenmann ...!utgpu!{ncrcan,ontmoh!moore}!ziebmef!cks cks@white.toronto.edu or ...!utgpu!{,csri!}cks
cks@white.toronto.edu (Chris Siebenmann) (06/28/89)
*Sigh ... of course, the second patch won't do people much good, since the original code has explicit escapes in it. I guess people will just have to apply the last two portions of the patch by hand (grr, grumble). -- "I shall clasp my hands together and bow to the corners of the world." Number Ten Ox, "Bridge of Birds" Chris Siebenmann ...!utgpu!{ncrcan,ontmoh!moore}!ziebmef!cks cks@white.toronto.edu or ...!utgpu!{,csri!}cks