Esempio n. 1
0
/*
** Temporary event handlers for keys pressed after the mark or goto-mark
** commands, If the key is valid, grab the key event and call the action
** procedure to mark (or go to) the selection, otherwise, remove the handler
** and give up.
*/
static void processMarkEvent(Widget w, XtPointer clientData, XEvent *event,
    	Boolean *continueDispatch, char *action, int extend)
{
    XKeyEvent *e = (XKeyEvent *)event;
    WindowInfo *window = WidgetToWindow(w);
    Modifiers modifiers;
    KeySym keysym;
    char *params[2], string[2];

    XtTranslateKeycode(TheDisplay, e->keycode, e->state, &modifiers,
    	    &keysym);
    if ((keysym >= 'A' && keysym <= 'Z') || (keysym >= 'a' && keysym <= 'z')) {
    	string[0] = toupper(keysym);
    	string[1] = '\0';
    	params[0] = string;
	params[1] = "extend";
    	XtCallActionProc(window->lastFocus, action, event, params,
		extend ? 2 : 1);
    	*continueDispatch = False;
    }
    XtRemoveEventHandler(w, KeyPressMask, False, markKeyCB, window);
    XtRemoveEventHandler(w, KeyPressMask, False, gotoMarkKeyCB, window);
    XtRemoveEventHandler(w, KeyPressMask, False, gotoMarkExtendKeyCB, window);
    XtRemoveTimeOut(window->markTimeoutID);
}
Esempio n. 2
0
KeySym XtGetActionKeysym(
    XEvent *event,
    Modifiers *modifiers_return)
{
    TMKeyContext tm_context;
    Modifiers modifiers;
    KeySym keysym, retval;

    LOCK_PROCESS;
    tm_context= _XtGetPerDisplay(event->xany.display)->tm_context;
    if (event->xany.type != KeyPress && event->xany.type != KeyRelease) {
	UNLOCK_PROCESS;
	return NoSymbol;
    }
    if (tm_context != NULL
	&& event == tm_context->event
	&& event->xany.serial == tm_context->serial ) {

	if (modifiers_return != NULL)
	    *modifiers_return = tm_context->modifiers;
	retval = tm_context->keysym;
	UNLOCK_PROCESS;
	return retval;
    }

    XtTranslateKeycode( event->xany.display, (KeyCode)event->xkey.keycode,
		        event->xkey.state, &modifiers, &keysym );

    if (modifiers_return != NULL)
	*modifiers_return = event->xkey.state & modifiers;

    UNLOCK_PROCESS;
    return keysym;
}
Esempio n. 3
0
/*
 * Event handler used by both TextField/TextArea to correctly process
 * cut/copy/paste keys such that interaction with our own
 * clipboard mechanism will work properly.
 *
 * client_data is MTextFieldPeer instance
 */
void 
Text_handlePaste(Widget w, XtPointer client_data, XEvent * event, Boolean * cont)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    KeySym keysym;
    Modifiers mods;

    /* Any event handlers which take peer instance pointers as
     * client_data should check to ensure the widget has not been
     * marked as destroyed as a result of a dispose() call on the peer
     * (which can result in the peer instance pointer already haven
     * been gc'd by the time this event is processed)
     */
    if (event->type != KeyPress || w->core.being_destroyed) {
        return;
    }

    XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
                       event->xkey.state, &mods, &keysym);

    /* Should be a temporary fix for 4052132 if a cleaner fix is found later */
    if ((event->xkey.state & ControlMask) && (keysym == 'v' || keysym == 'V'))
        keysym = osfXK_Paste;
    if ((event->xkey.state & ShiftMask) && (keysym == osfXK_Insert))
        keysym = osfXK_Paste;

    switch (keysym) {
        case osfXK_Paste:
            /* If we own the selection, then paste the data directly */
            if (awtJNI_isSelectionOwner(env, "CLIPBOARD")) {
                JNU_CallMethodByName(env, NULL, (jobject) client_data, 
				     "pasteFromClipboard", "()V");
                if ((*env)->ExceptionOccurred(env)) {
                    (*env)->ExceptionDescribe(env);
                    (*env)->ExceptionClear(env);
                }
                *cont = FALSE;
            }
            break;

        case osfXK_Cut:
        case osfXK_Copy:
            /* For some reason if we own the selection, our loseSelection
             * callback is not automatically called on cut/paste from
             * text widgets.
             */
            if (awtJNI_isSelectionOwner(env, "CLIPBOARD")) {
                awtJNI_notifySelectionLost(env, "CLIPBOARD");
            }
            break;
        default:
            break;
    }
}
Esempio n. 4
0
void kb_event(Display *display, XEvent *event)
{
    KeySym keysym;
    Modifiers dummy;
    u8 key_index;
    int modifiers;

    if ((event->type != KeyPress) && (event->type != KeyRelease)) {
	return;
    }

    modifiers = event->xkey.state & ShiftMask;
    modifiers |= (event->xkey.state & ControlMask) >> 1;
    
    XtTranslateKeycode(display, event->xkey.keycode, 0, &dummy, &keysym);

    key_index = 0;
    
    if ((keysym & 0xff00) == 0x0000) { /* Latin1 charset */
	if (!(keysym < 0x80)) {
	    return;
	}
	key_index = keysym_translate[keysym & 0xff];
    }

    if ((keysym & 0xff00) == 0xff00) { /* miscellaneous keys */
	if (keysym == XK_Escape) {
	    key_index = 14;
	} else if (keysym == XK_Return) {
	    key_index = 26;
	} else if ((keysym == XK_Left) || (keysym == XK_KP_Left)) {
	    key_index = 39;
	} else if ((keysym == XK_Right) || (keysym == XK_KP_Right)) {
	    key_index = 40;
	}
    }

    if (key_index) {
	/*
	 * NOTE: We can get away with calling both handler functions because
	 * they both operate on static data. We really should be using a
	 * registered callback, but that would require more work than I feel
	 * like doing at the present time.
	 */
	if (event->type == KeyPress) {
	    apple2_press_keyboard(apple2, decode_key[key_index][modifiers]);
	}
	sc3k_keyboard_event(key_index | ((event->type != KeyPress) << 7));
	msx_keyboard_event(key_index | ((event->type != KeyPress) << 7));
    }
}
Esempio n. 5
0
static void GrabAllCorrectKeys(
    Widget widget,
    TMTypeMatch typeMatch,
    TMModifierMatch modMatch,
    GrabActionRec* grabP)
{
    Display *dpy = XtDisplay(widget);
    KeyCode *keycodes, *keycodeP;
    Cardinal keycount;
    Modifiers careOn = 0;
    Modifiers careMask = 0;

    if (modMatch->lateModifiers) {
	Boolean resolved;
	resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers,
					  &careOn, &careMask);
	if (!resolved) return;
    }
    careOn |= modMatch->modifiers;
    careMask |= modMatch->modifierMask;

    XtKeysymToKeycodeList(
	    dpy,
	    (KeySym)typeMatch->eventCode,
	    &keycodes,
	    &keycount
			 );
    if (keycount == 0) return;
    for (keycodeP = keycodes; keycount--; keycodeP++) {
	if (modMatch->standard) {
	    /* find standard modifiers that produce this keysym */
	    KeySym keysym;
	    int std_mods, least_mod;
	    Modifiers modifiers_return;
	    XtTranslateKeycode( dpy, *keycodeP, (Modifiers)0,
			        &modifiers_return, &keysym );
	    if (careOn & modifiers_return)
		return;
	    if (keysym == typeMatch->eventCode) {
		XtGrabKey(widget, *keycodeP, careOn,
			  grabP->owner_events,
			  grabP->pointer_mode,
			  grabP->keyboard_mode
			);
		/* continue; */		/* grab all modifier combinations */
	    }
	    least_mod = modifiers_return & (~modifiers_return + 1);
	    for (std_mods = modifiers_return;
		 std_mods >= least_mod; std_mods--) {
		Modifiers dummy;
		 /* check all useful combinations of modifier bits */
		if (modifiers_return & std_mods &&
		    !(~modifiers_return & std_mods)) {
		    XtTranslateKeycode( dpy, *keycodeP,
					(Modifiers)std_mods,
					&dummy, &keysym );
		    if (keysym == typeMatch->eventCode) {
			XtGrabKey(widget, *keycodeP,
				  careOn | (Modifiers) std_mods,
				  grabP->owner_events,
				  grabP->pointer_mode,
				  grabP->keyboard_mode
				);
			/* break; */	/* grab all modifier combinations */
		    }
		}
	    }
	} else /* !event->standard */ {
	    XtGrabKey(widget, *keycodeP, careOn,
		      grabP->owner_events,
		      grabP->pointer_mode,
		      grabP->keyboard_mode
		    );
	}
    }
    XtFree((char *)keycodes);
}
/*
 * Event handler used by both TextField/TextArea to correctly process
 * cut/copy/paste keys such that interaction with our own clipboard mechanism
 * will work properly.
 */
void
Text_handlePaste(Widget w, XtPointer client_data, XEvent * event, Boolean * cont)
{
	KeySym          keysym;
	long            mods;
	JNIEnv         *env;
	jobject         this = (jobject) client_data;

	if ((*JVM)->AttachCurrentThread(JVM, (void **) &env, NULL) != 0)
		return;

	/*
	 * Any event handlers which take peer instance pointers as
	 * client_data should check to ensure the widget has not been marked
	 * as destroyed as a result of a dispose() call on the peer (which
	 * can result in the peer instance pointer already haven been gc'd by
	 * the time this event is processed)
	 */

	if (w->core.being_destroyed)
		return;


	if (event->type == KeyPress) {

		XtTranslateKeycode(event->xkey.display, (KeyCode) event->xkey.keycode,
			  event->xkey.state, (Modifiers *) & mods, &keysym);

		/*
		 * allow Ctrl-V and Shift-Insert to function as Paste when VM
		 * has clipboard, otherwise the applicatin hangs
		 *//* Bug#unknown */
		if ((event->xkey.state & ControlMask) && (keysym == 'v' || keysym == 'V')) {	/* Bug#unknown */
			keysym = osfXK_Paste;	/* Bug#unknown */
		}		/* Bug#unknown */
		if ((event->xkey.state & ShiftMask) && (keysym == (osfXK_Insert & 0xffff))) {	/* Bug#unknown */
			keysym = osfXK_Paste;	/* Bug#unknown */
		}		/* Bug#unknown */
		switch (keysym) {
		case osfXK_Paste:
			/*
			 * If we own the selection, then paste the data
			 * directly
			 */
			if (awt_isSelectionOwner(env, "CLIPBOARD")) {
				(*env)->CallVoidMethod(env, this, MCachedIDs.MTextPeer_pasteFromClipboardMID);
				*cont = FALSE;
			}
			break;
		case osfXK_Cut:
		case osfXK_Copy:
			/*
			 * For some reason if we own the selection, our
			 * loseSelection callback is not automatically called
			 * on cut/paste from text widgets.
			 */
			if (awt_isSelectionOwner(env, "CLIPBOARD")) {
				awt_notifySelectionLost(env, "CLIPBOARD");
			}
			break;
		}
	}
}
Esempio n. 7
0
//
// Input from motif text-widget with recall
// Returns 1 if return i pressed, else 0.
//
int mrm_TextInput( Widget w, XEvent *event, char *recall, int line_size, 
	int recall_size, int *current_recall_line)
{
  KeySym keysym;
  Modifiers mod;
  int 	pos;
  char 	*text;
  char 	newtext[160];
  int	i;
  XmTextPosition   left, right;
  char  *s, *t;

  text = XmTextGetString( w);
  XtTranslateKeycode( flow_Display(w), event->xkey.keycode, event->xkey.state, 
	&mod, &keysym);
  keysym &= 0xFFFF;
  switch ( keysym) 
  {
    case XK_Return:
    case XK_Linefeed:
      // Insert in recall buffer
      if ( strcmp( text, "") != 0)
      {
        for ( i = recall_size - 2; i >= 0; i--)
          strcpy( recall + (i+1) * line_size, recall + i * line_size);
        strncpy( recall, text, line_size);
        recall[line_size-1] = 0;
      }
      *current_recall_line = 0;
      return 1;
    case XK_Up:
      (*current_recall_line)++;
      if ( *current_recall_line > recall_size - 1)
        *current_recall_line = recall_size - 1;
      XmTextSetString( w, recall + (*current_recall_line - 1) * line_size);
      XmTextSetCursorPosition( w, 
		strlen(recall + (*current_recall_line - 1) * line_size));
      break;
    case XK_Down:
      if ( *current_recall_line == 0)
        XmTextSetString( w, "");
      else if ( *current_recall_line == 1)
      {
        XmTextSetString( w, "");
        (*current_recall_line)--;
      }
      else
      {
        (*current_recall_line)--;
        XmTextSetString( w, recall + (*current_recall_line - 1) * line_size);
        XmTextSetCursorPosition( w, 
		strlen(recall + (*current_recall_line - 1) * line_size));
      }
      break;
    case XK_Left:
      XmTextClearSelection( w, CurrentTime);
      pos = XmTextGetCursorPosition( w);
      if ( pos == 0)
        break;
      pos--;
      XmTextSetCursorPosition( w, pos);
      break;
    case XK_Right:
      XmTextClearSelection( w, CurrentTime);
      pos = XmTextGetCursorPosition( w);
      if ( pos >= line_size - 1)
        break;
      pos++;
      if ( pos > strlen(text))
        break;
      XmTextSetCursorPosition( w, pos);
      break;
    case XK_BackSpace:
    case 65535:
      if ( XmTextGetSelectionPosition( w, &left, &right)) {
        for ( s = text + left, t = text + right; *t; s++,t++)
	  *s = *t; 
        *s = 0;
        XmTextSetString( w, text);
        XmTextSetCursorPosition( w, left);
      }
      else {
        pos = XmTextGetCursorPosition( w);
        if ( pos == 0)
          break;
        if ( pos == 1)
          strcpy( newtext, "");
        else
          strncpy( newtext, text, pos-1);
        newtext[pos-1] = 0;
        strncat( newtext, &text[pos], sizeof( newtext));
        XmTextSetString( w, newtext);
        XmTextSetCursorPosition( w, pos-1);
      }
      break;
    default:
      if ( event->xkey.state & ControlMask)
        return 0;
      if ( keysym > 256)
        return 0;

      if ( XmTextGetSelectionPosition( w, &left, &right)) {
        for ( s = text + left, t = text + right; *t; s++,t++)
	  *s = *t; 
        *s = 0;
        XmTextSetCursorPosition( w, left);
      }
      pos = XmTextGetCursorPosition( w);
      if ( pos >= line_size - 1)
        break;
      if ( pos == 0)
        strcpy( newtext, "");
      else
        strncpy( newtext, text, pos);
      newtext[pos] = keysym;
      newtext[pos+1] = 0;
      strncat( newtext, &text[pos], sizeof( newtext));
      XmTextSetString( w, newtext);
      XmTextSetCursorPosition( w, pos+1);
  }
  return 0;
}
Esempio n. 8
0
File: gwin.c Progetto: deadpixi/sam
static void
Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
{
    static unsigned char compose[5];
    static int composing = -2;
    int kind = Kraw;

    int c, len, minmod;
    KeySym k, mk;
    Charfunc f;
    Modifiers md;
    char buf[100] = {0};

    c = 0;
    len = 0;

    /* Translate the keycode into a key symbol. */
    if(e->xany.type != KeyPress)
        return;
    XkbTranslateKeyCode(xkb, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k);
    XkbTranslateKeySym(e->xany.display, &k, e->xkey.state, buf, sizeof(buf) - 1, &len);

    /* Check to see if it's a specially-handled key first. */
    for (Keymapping *m = keymappings; m; m = m->next){
        KeySym u = NoSymbol;
        KeySym l = NoSymbol;
        XConvertCase(k, &l, &u);

        /* Note that magic bit manipulation here - we want to check that the
         * modifiers that are specified for the binding are all pressed, but
         * we allow other modifiers to be as well. This is because when NumLock
         * is on, it's always added to the modifier mask.
         */
        if (l == m->s || m->s == XK_VoidSymbol){
            if (m->m == 0 || (m->m & ~e->xkey.state) == 0){
                switch (m->c){
                    case Cnone:
                        return;

                    case Cdefault:
                        continue;

                    default:
                        f = ((GwinWidget)w)->gwin.gotchar;
                        if (f)
                            (*f)(m->c, m->k, Tcurrent, 0, 0, m->a);
                        return;
                }
            }
        }
    }

    /*
     * The following song and dance is so we can have our chosen
     * modifier key behave like a compose key, i.e, press and release
     * and then type the compose sequence, like Plan 9.  We have
     * to find out which key is the compose key first though.
     */
    if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose
            && composing == -2 && modmap) {
        minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod;
        for (c = minmod; c < minmod+keypermod; c++) {
            XtTranslateKeycode(e->xany.display,
                    modmap->modifiermap[c],
                        e->xkey.state, &md, &mk);
            if (k == mk) {
                composing = -1;
                break;
            }
        }
        return;
    }

    /* Handle Multi_key separately, since it isn't a modifier */
    if(k == XK_Multi_key) {
        composing = -1;
        return;
    }

    if(k == NoSymbol || k > 0xff00)
        return;

    /* Check to see if we are in a composition sequence */
    if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask)
            && composing == -2)
        composing = -1;
    if (composing > -2) {
        compose[++composing] = k;
        if ((*compose == 'X') && (composing > 0)) {
            if ((k < '0') || (k > 'f') ||
                    ((k > '9') && (k < 'a'))) {
                STUFFCOMPOSE();
                c = (uint16_t)k;
                composing = -2;
            } else if (composing == 4) {
                c = unicode(compose);
                if (c == -1) {
                    STUFFCOMPOSE();
                    c = (uint16_t)compose[4];
                }
                composing = -2;
            }
        } else if (composing == 1) {
            c = (int)latin1(compose);
            if (c == -1) {
                STUFFCOMPOSE();
                c = (uint16_t)compose[1];
            }
            composing = -2;
        }
    } else {
        if (composing >= 0) {
            composing++;
            STUFFCOMPOSE();
        }
        c = keysymtoshort(k);
        composing = -2;
    }

    if (composing >= -1)
        return;

    f = ((GwinWidget)w)->gwin.gotchar;
    if(f)
        (*f)(c, kind, Tcurrent, 0, 0, NULL);
}
Esempio n. 9
0
/*
**  Button1 press: evaluate at curpos
**  Button2 press: clear marks.  start mark at curpos.
**  Button2 motion: clear old stop mark.  stop mark at curpos
**  Button2 release: same as motion.
*/
static void video_event_handler(Widget w, XtPointer clientData, XEvent *event, Boolean *b)
{
	PLOT *plot = (PLOT *)clientData;
	XButtonEvent *butevent;
	XMotionEvent *motevent;
	XKeyEvent *keyevent;
	char *keybuf;
	KeySym key_sym;
	Modifiers mod_return;
	Widget ew;

	switch (event->type)
	{
		case KeyRelease:
			keyevent = (XKeyEvent *)event;
			ew = XtWindowToWidget(XtDisplay(w), keyevent->window);
			if (ew != plot->plot_widget)
				panel_event_handler(ew, (XtPointer)plot->panel, event, b);
			else
			{
				XtTranslateKeycode(XtDisplay(w), keyevent->keycode, 0, &mod_return, &key_sym);
				if ((keybuf = XKeysymToString(key_sym)) != NULL)
				{
					if (KEY_IS_UP(keybuf))
					{
						panel_unzoom(plot->panel);
					}
					else
					{
						panel_handle_keyrelease(w, plot, keyevent, keybuf);
					}
				}
			}
			break;

		case ButtonPress:
			butevent = (XButtonEvent *) event;
			switch (butevent->button)
			{
				case Button1:
					break;

				case Button2:
					break;

				case Button3:
					XmMenuPosition(plot->plot_popupmenu_widget, butevent);
					XtManageChild(plot->plot_popupmenu_widget);
					break;

				default:
					break;
			}
			break;

		case ButtonRelease:
			butevent = (XButtonEvent *) event;
			switch (butevent->button)
			{
				case Button1:
					break;
				case Button2:
					break;
				case Button3:
					break;
				default:
					break;
			}
			break;

		case MotionNotify:
			motevent = (XMotionEvent *)event;
			if (motevent->state & Button1Mask)
			{
			}
			else if (motevent->state & Button2Mask)
			{
			}
			else if (motevent->state & Button2Mask)
			{
			}
			break;

		default:
			break;
	}
}
Esempio n. 10
0
static void
Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
{
	static unsigned char compose[5];
	static int composing = -2;
    int composed = 0;

	int c, minmod;
	KeySym k, mk;
	Charfunc f;
	Modifiers md;

	/*
	 * I tried using XtGetActionKeysym, but it didn't seem to
	 * do case conversion properly
	 * (at least, with Xterminal servers and R4 intrinsics)
	 */
	if(e->xany.type != KeyPress)
		return;
	XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode,
		        e->xkey.state, &md, &k);
	/*
	 * The following song and dance is so we can have our chosen
	 * modifier key behave like a compose key, i.e, press and release
	 * and then type the compose sequence, like Plan 9.  We have
	 * to find out which key is the compose key first 'though.
	 */
	if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose
			&& composing == -2 && modmap) {
		minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod;
		for (c = minmod; c < minmod+keypermod; c++) {
			XtTranslateKeycode(e->xany.display,
					modmap->modifiermap[c],
	        			e->xkey.state, &md, &mk);
			if (k == mk) {
				composing = -1;
				break;
			}
		}
		return;
	}
	/* Handle Multi_key separately, since it isn't a modifier */
	if(k == XK_Multi_key) {
		composing = -1;
		return;
	}
	if(k == NoSymbol)
		return;
	if(k&0xFF00){
		switch(k){
		case XK_BackSpace:
		case XK_Tab:
		case XK_Escape:
		case XK_Delete:
		case XK_KP_0:
		case XK_KP_1:
		case XK_KP_2:
		case XK_KP_3:
		case XK_KP_4:
		case XK_KP_5:
		case XK_KP_6:
		case XK_KP_7:
		case XK_KP_8:
		case XK_KP_9:
		case XK_KP_Divide:
		case XK_KP_Multiply:
		case XK_KP_Subtract:
		case XK_KP_Add:
		case XK_KP_Decimal:
			k &= 0x7F;
			break;
		case XK_Linefeed:
			k = '\r';
			break;
		case XK_KP_Enter:
		case XK_Return:
			k = '\n';
			break;
		case XK_Left:
		case XK_Down:
		case XK_Right:
		case XK_Next:
			k = 0x80; /* VIEW -- "Scroll" */
			break;
		case XK_Up:
		case XK_Prior:
			k = 0x81; /* PREVIEW -- "Scroll back" */
			break;
		default:
			return;	/* not ISO-1 or tty control */
		}
	}
	/* Compensate for servers that call a minus a hyphen */
	if(k == XK_hyphen)
		k = XK_minus;
	/* Do control mapping ourselves if translator doesn't */
	if((e->xkey.state&ControlMask) && !(md&ControlMask))
		k &= 0x9f;
	if(k == NoSymbol)
		return;
	/* Check to see if we are in a composition sequence */
	if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask)
			&& composing == -2)
		composing = -1;
	if (composing > -2) {
		compose[++composing] = k;
		if ((*compose == 'X') && (composing > 0)) {
			if ((k < '0') || (k > 'f') ||
					((k > '9') && (k < 'a'))) {
				STUFFCOMPOSE();
				c = (unsigned short)k;
				composing = -2;
			} else if (composing == 4) {
				c = unicode(compose);
				if (c == -1) {
					STUFFCOMPOSE();
					c = (unsigned short)compose[4];
				} else
                    composed = 1;
				composing = -2;
			}
		} else if (composing == 1) {
			c = (int)latin1(compose);
			if (c == -1) {
				STUFFCOMPOSE();
				c = (unsigned short)compose[1];
			} else
                composed = 1;
			composing = -2;
		}
	} else {
		if (composing >= 0) {
			composing++;
			STUFFCOMPOSE();
		}
		c = (unsigned short)k;
		composing = -2;
	}

	if (composing >= -1)
		return;

	f = ((GwinWidget)w)->gwin.gotchar;
	if(f)
		(*f)(c, composed);
}