+static void keymap_lookup_key(MappedKey *mk, KeySym sym, const char *what) {
+ const MappedModifier *shift, *xshift;
+ int col, kc;
+ char cols[MAXMAPCOL+1];
+
+ memset(cols,'.',MAXMAPCOL);
+ cols[MAXMAPCOL]= 0;
+
+ for (col=0; col<mapwidth && col<MAXMAPCOL; col++) {
+
+#define CHECK_SHIFT(sh) do{ \
+ if ((sh) && (sh)->isdef!='y') { \
+ cols[col]= (sh)->isdef; \
+ continue; \
+ } \
+ }while(0)
+
+ shift= col & 1 ? &mm_shift : 0;
+ CHECK_SHIFT(shift);
+
+ xshift= col >= 4 ? &mm_isol3shift :
+ col >= 2 ? &mm_modeswitch :
+ 0;
+ CHECK_SHIFT(xshift);
+
+ for (kc=kc_min; kc <= kc_max; kc++) {
+ if (mapping[(kc-kc_min)*mapwidth + col] == sym)
+ goto found;
+ }
+ cols[col]= '_';
+ }
+ fprintf(stderr,"\n"
+ "Unable to find a key to press to generate %s.\n"
+ "(Technical details: cols:%s sh:%c:%d modesw:%c:%d isol3:%c:%d)\n",
+ what, cols,
+#define SH_DETAILS(sh) mm_##sh.isdef, mm_##sh.kc
+ SH_DETAILS(shift), SH_DETAILS(modeswitch), SH_DETAILS(isol3shift));
+ fatal("Keymap is unsuitable!");
+
+ found:;
+ int *fill= mk->kc;
+
+ if (xshift) *fill++ = xshift->kc;
+ if (shift) *fill++ = shift->kc;
+ *fill += kc;
+ mk->len= fill - mk->kc;
+}
+
+static void keymap_startup(void) {
+ xassert( XDisplayKeycodes(disp,&kc_min,&kc_max) );
+ xassert( mapping= XGetKeyboardMapping(disp, kc_min, kc_max-kc_min+1,
+ &mapwidth) );
+
+ XModifierKeymap *modmap;
+ xassert( modmap= XGetModifierMapping(disp) );
+
+ /* find a shift keycode */
+ mm_shift.isdef= 'x';
+ int modent;
+ for (modent=0; modent<modmap->max_keypermod; modent++) {
+ KeySym shiftsym= modmap->modifiermap[modent];
+ if (shiftsym==NoSymbol) continue;
+ keymap_lookup_modifier(&mm_shift, shiftsym, 's');
+ if (mm_shift.isdef!='y') break;
+ }
+
+ /* find keycodes for mode_switch (column+=2) and ISO L3 shift (column+=4) */
+ keymap_lookup_modifier(&mm_modeswitch, XK_Mode_switch, 0);
+ keymap_lookup_modifier(&mm_isol3shift, XK_ISO_Level3_Shift, 0);
+
+ XFreeModifiermap(modmap);
+
+#define KEY_MAP_LOOKUP(xk) \
+ keymap_lookup_key(&mk_##xk, xk, #xk);
+ KEYS(KEY_MAP_LOOKUP)
+
+ XFree(mapping);
+ mapping= 0;