add: if (x_modifier_keymap != NULL) XFreeModifiermap(x_modifier_keymap);
context: x_reset_modifier_mapping (Display *display){  int modifier_index, modifier_key, column, mkpm;  int warned_about_overlapping_modifiers = 0;  int warned_about_predefined_modifiers  = 0;  int warned_about_duplicate_modifiers   = 0;  int meta_bit  = 0;  int hyper_bit = 0;  int super_bit = 0;  int alt_bit   = 0;  int mode_bit  = 0;  XModifierKeymap *x_modifier_keymap = XGetModifierMapping (display);#define modwarn(name,old,other)						    \  wwarning ("%s (0x%x) generates %s, which is generated by %s.\n\n",        \		  name, code, index_to_name (old), other),		    \  warned_about_overlapping_modifiers = 1#define modbarf(name,other)						    \  wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n",            \		  name, code, other),					    \  warned_about_predefined_modifiers = 1#define check_modifier(name,mask)					    \  if ((1<<modifier_index) != mask)					    \    wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n",          \		    name, code, index_to_name (modifier_index)),	    \    warned_about_predefined_modifiers = 1#define store_modifier(name,old)					   \  if (old && old != modifier_index)					   \    wwarning ("%s (0x%x) generates both %s and %s, which is nonsensical.\n\n",\		    name, code, index_to_name (old),			   \		    index_to_name (modifier_index)),			   \    warned_about_duplicate_modifiers = 1;				   \  if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift");	   \  else if (modifier_index == LockMapIndex) modbarf (name,"ModLock");	   \  else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \  else if (sym == XK_Mode_switch)					   \    mode_bit = modifier_index; /* Mode_switch is special, see below... */  \  else if (modifier_index == meta_bit && old != meta_bit)		   \    modwarn (name, meta_bit, "Meta");					   \  else if (modifier_index == super_bit && old != super_bit)		   \    modwarn (name, super_bit, "Super");					   \  else if (modifier_index == hyper_bit && old != hyper_bit)		   \    modwarn (name, hyper_bit, "Hyper");					   \  else if (modifier_index == alt_bit && old != alt_bit)			   \    modwarn (name, alt_bit, "Alt");					   \  else									   \    old = modifier_index;  mkpm = x_modifier_keymap->max_keypermod;  for (modifier_index = 0; modifier_index < 8; modifier_index++)    for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {      KeySym last_sym = 0;      for (column = 0; column < 4; column += 2) {	KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm							  + modifier_key];	KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);	if (sym == last_sym) continue;	last_sym = sym;	switch (sym) {	case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;	case XK_Meta_L:     store_modifier ("Meta_L", meta_bit); break;	case XK_Meta_R:     store_modifier ("Meta_R", meta_bit); break;	case XK_Super_L:    store_modifier ("Super_L", super_bit); break;	case XK_Super_R:    store_modifier ("Super_R", super_bit); break;	case XK_Hyper_L:    store_modifier ("Hyper_L", hyper_bit); break;	case XK_Hyper_R:    store_modifier ("Hyper_R", hyper_bit); break;	case XK_Alt_L:      store_modifier ("Alt_L", alt_bit); break;	case XK_Alt_R:      store_modifier ("Alt_R", alt_bit); break;	case XK_Control_L:  check_modifier ("Control_L", ControlMask); break;	case XK_Control_R:  check_modifier ("Control_R", ControlMask); break;	case XK_Shift_L:    check_modifier ("Shift_L", ShiftMask); break;	case XK_Shift_R:    check_modifier ("Shift_R", ShiftMask); break;	case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask); break;	case XK_Caps_Lock:  check_modifier ("Caps_Lock", LockMask); break;	/* It probably doesn't make any sense for a modifier bit to be	   assigned to a key that is not one of the above, but OpenWindows	   assigns modifier bits to a couple of random function keys for	   no reason that I can discern, so printing a warning here would	   be annoying. */	}      }    }#undef store_modifier#undef check_modifier#undef modwarn#undef modbarf  /* If there was no Meta key, then try using the Alt key instead.     If there is both a Meta key and an Alt key, then the Alt key     is not disturbed and remains an Alt key. */  if (! meta_bit && alt_bit)    meta_bit = alt_bit, alt_bit = 0;  /* mode_bit overrides everything, since it's processed down inside of     XLookupString() instead of by us.  If Meta and Mode_switch both     generate the same modifier bit (which is an error), then we don't     interpret that bit as Meta, because we can't make XLookupString()     not interpret it as Mode_switch; and interpreting it as both would     be totally wrong. */  if (mode_bit)    {      const char *warn = 0;      if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;      else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;      else if (mode_bit == super_bit) warn = "Super", super_bit = 0;      else if (mode_bit == alt_bit)   warn = "Alt",   alt_bit   = 0;      if (warn)	{	  wwarning	    ("%s is being used for both Mode_switch and %s.\n\n",	     index_to_name (mode_bit), warn),	    warned_about_overlapping_modifiers = 1;	}    }  MetaIndex   = meta_bit;  HyperIndex  = hyper_bit;  SuperIndex  = super_bit;  AltIndex    = alt_bit;  ModeIndex   = mode_bit;}