Index: lib/forms.c
===================================================================
RCS file: /cvsroot/xforms/xforms/lib/forms.c,v
retrieving revision 1.7
diff -u -p -r1.7 forms.c
--- lib/forms.c	24 Apr 2003 09:35:34 -0000	1.7
+++ lib/forms.c	30 May 2003 11:38:43 -0000
@@ -1228,7 +1228,8 @@ fl_do_shortcut(FL_FORM * form, int key,
 }
 
 static void
-fl_keyboard(FL_FORM * form, int key, FL_Coord x, FL_Coord y, void *xev)
+fl_keyboard(int event,
+	    FL_FORM * form, int key, FL_Coord x, FL_Coord y, void *xev)
 {
     FL_OBJECT *obj, *obj1, *special;
 
@@ -1257,20 +1258,20 @@ fl_keyboard(FL_FORM * form, int key, FL_
 	if (key > 255)
 	{
 	    if (IsLeft(key) || IsRight(key) || IsHome(key) || IsEnd(key))
-		fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev);
+		fl_handle_object(focusobj, event, x, y, key, xev);
 	    else if ((IsUp(key) || IsDown(key) ||
 		      IsPageUp(key) || IsPageDown(key)) &&
 		     (focusobj->wantkey & FL_KEY_TAB))
-		fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev);
+		fl_handle_object(focusobj, event, x, y, key, xev);
 	    else if (special && (special->wantkey & FL_KEY_SPECIAL))
 	    {
 		/* moving the cursor in input field that does not have focus
 		   looks weird */
 		if (special->objclass != FL_INPUT)
-		    fl_handle_object(special, FL_KEYBOARD, x, y, key, xev);
+		    fl_handle_object(special, event, x, y, key, xev);
 	    }
 	    else if (key == XK_BackSpace || key == XK_Delete)
-		fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev);
+		fl_handle_object(focusobj, event, x, y, key, xev);
 	    return;
 	}
 
@@ -1294,7 +1295,7 @@ fl_keyboard(FL_FORM * form, int key, FL_
 	    fl_handle_object(obj, FL_FOCUS, x, y, 0, xev);
 	}
 	else if (focusobj->wantkey != FL_KEY_SPECIAL)
-	    fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev);
+	    fl_handle_object(focusobj, event, x, y, key, xev);
 	return;
     }
 
@@ -1304,11 +1305,11 @@ fl_keyboard(FL_FORM * form, int key, FL_
 
     /* space is an exception for browser */
     if ((key > 255 || key == ' ') && (special->wantkey & FL_KEY_SPECIAL))
-	fl_handle_object(special, FL_KEYBOARD, x, y, key, xev);
+	fl_handle_object(special, event, x, y, key, xev);
     else if (key < 255 && (special->wantkey & FL_KEY_NORMAL))
-	fl_handle_object(special, FL_KEYBOARD, x, y, key, xev);
+	fl_handle_object(special, event, x, y, key, xev);
     else if (special->wantkey == FL_KEY_ALL)
-	fl_handle_object(special, FL_KEYBOARD, x, y, key, xev);
+	fl_handle_object(special, event, x, y, key, xev);
 
 #if FL_DEBUG >= ML_INFO
     M_info("KeyBoard", "(%d %d)pushing %d to %s\n", x, y, key, special->label);
@@ -1328,7 +1329,7 @@ fl_handle_form(FL_FORM * form, int event
     if (form->deactivated && event != FL_DRAW)
 	return;
 
-    if (form->parent_obj && form->parent_obj->active == DEACTIVATED && 
+    if (form->parent_obj && form->parent_obj->active == DEACTIVATED &&
           event != FL_DRAW)
 	return;
 
@@ -1341,7 +1342,7 @@ fl_handle_form(FL_FORM * form, int event
     if (event != FL_STEP && event != FL_DRAW)
     {
 	if (event == FL_PUSH || event == FL_RELEASE || event == FL_ENTER ||
-	    event == FL_LEAVE || event == FL_KEYBOARD || event == FL_MOUSE)
+	    event == FL_LEAVE || event == FL_KEYPRESS || event == FL_MOUSE)
 	{
 	    xx = fl_mousex;
 	    yy = fl_mousey;
@@ -1434,8 +1435,9 @@ fl_handle_form(FL_FORM * form, int event
 	fl_pushobj = NULL;
 	fl_handle_object(obj, FL_RELEASE, xx, yy, key, xev);
 	break;
-    case FL_KEYBOARD:		/* A key was pressed */
-	fl_keyboard(form, key, xx, yy, xev);
+    case FL_KEYPRESS:		/* A key was pressed */
+    case FL_KEYRELEASE:		/* A key was released */
+	fl_keyboard(event, form, key, xx, yy, xev);
 	break;
     case FL_STEP:		/* A simple step */
 	obj1 = fl_find_first(form, FL_FIND_AUTOMATIC, 0, 0);
@@ -1520,11 +1522,68 @@ hack_test(void)
 
 /* formevent is either FL_KEYPRESS or FL_KEYRELEASE */
 static void
+dispatch_key(FL_FORM * form, int event, KeySym keysym,
+	     unsigned char const * keybuf, int kbuflen, XEvent * xev)
+{
+    if (kbuflen < 0) {
+
+	if ( kbuflen != INT_MIN ) {
+
+	    /* buffer overflow, should not happen */
+	    M_err("DoKeyBoard", "keyboad buffer overflow ?");
+
+	} else {
+
+	    M_err("DoKeyBoard", "fl_XLookupString failed ?");
+
+	}
+
+    } else {
+
+	/* ignore modifier keys as they don't cause action and are
+	   taken care of by the lookupstring routine */
+
+	if (IsModifierKey(keysym))
+	    ;
+	else if (IsTab(keysym)) {
+
+	    /* fake a tab key. */
+	    /* some system shift+tab does not generate tab */
+
+	    fl_handle_form(form, event, 9, xev);
+
+	}
+#if (FL_DEBUG >= ML_DEBUG )
+	else if (keysym == XK_F10)	/* && controlkey_down(fl_keymask)) */
+	    hack_test();
+#endif
+
+	/* pass all keys to the handler */
+	else if (IsCursorKey(keysym) || kbuflen == 0)
+	    fl_handle_form(form, event, keysym, xev);
+	else {
+
+	    unsigned char const *ch;
+
+	    /* all regular keys, including mapped strings */
+
+	    for (ch = keybuf; ch < (keybuf + kbuflen) && form; ch++)
+		fl_handle_form(form, event, *ch, xev);
+
+	}
+    }
+}
+
+
+/* formevent is either FL_KEYPRESS or FL_KEYRELEASE */
+static void
 do_keyboard(XEvent * xev, int formevent)
 {
 
     Window win;
-    int kbuflen;
+    KeySym keysym = 0;
+    static KeySym last_pressed_keysym;
+    unsigned char * ch;
 
     /* before doing anything, save the current modifier key for the handlers */
     win = xev->xkey.window;
@@ -1546,65 +1605,26 @@ do_keyboard(XEvent * xev, int formevent)
 
     if ( keyform ) {
 
-	KeySym keysym = 0;
-	unsigned char keybuf[227];
+	static KeySym keysym = 0;
+	static int kbuflen;
+	static unsigned char keybuf[227];
+
+	/* Note that the behaviour of XmbLookupString is undefined on a
+	   KeyRelease event, so we do not attempt to call fl_XLookupString.
+	   Rather, we store the keysym of the previous FL_KEYPRESS event
+	   and dispatch that. */
+	if (formevent == FL_KEYRELEASE) {
+	    dispatch_key(keyform, FL_KEYRELEASE, keysym, keybuf, kbuflen, xev);
+	    return;
+	}
 
 	kbuflen = fl_XLookupString((XKeyEvent *) xev, (char *) keybuf,
 				   sizeof(keybuf), &keysym);
-	
-	if (kbuflen < 0) {
-	    
-	    if ( kbuflen != INT_MIN ) {
-		
-		/* buffer overflow, should not happen */
-		M_err("DoKeyBoard", "keyboad buffer overflow ?");
-		
-	    } else {
-
-		M_err("DoKeyBoard", "fl_XLookupString failed ?");
-	    
-	    }
-
-	} else {
-	    
-	    /* ignore modifier keys as they don't cause action and are
-	       taken care of by the lookupstring routine */
-	    
-	    if (IsModifierKey(keysym))
-		;
-	    else if (IsTab(keysym)) {
-		
-		/* fake a tab key. */
-		/* some system shift+tab does not generate tab */
-		
-		fl_handle_form(keyform, formevent, 9, xev);
-
-	    }
-#if (FL_DEBUG >= ML_DEBUG )
-	    else if (keysym == XK_F10)	/* && controlkey_down(fl_keymask)) */
-		hack_test();
-#endif
-	    
-	    /* pass all keys to the handler */
-	    else if (IsCursorKey(keysym) || kbuflen == 0)
-		fl_handle_form(keyform, formevent, keysym, xev);
-	    else {
-
-		unsigned char *ch;
-
-		/* all regular keys, including mapped strings */
-
-		for (ch = keybuf; ch < (keybuf + kbuflen) && keyform; ch++)
-		    fl_handle_form(keyform, formevent, *ch, xev);
-
-	    }
-	    
-	}
-
+	dispatch_key(keyform, FL_KEYPRESS, keysym, keybuf, kbuflen, xev);
     }
-
 }
 
+
 FL_FORM_ATCLOSE
 fl_set_form_atclose(FL_FORM * form, FL_FORM_ATCLOSE fmclose, void *data)
 {

