head	1.27;
access;
symbols
	core-8-5-9:1.23
	core-8-5-8:1.23
	macosx-cocoa-merge:1.25
	macosx-cocoa-premerge:1.24
	macosx-carbon-freeze:1.24
	core-8-5-7:1.23
	core-8-5-6:1.23
	core-8-6-b1:1.24
	core-8-6-a3:1.23
	core-8-5-5:1.23
	core-8-6-a2:1.23
	core-8-5-4:1.23
	core-8-5-3:1.23
	core-8-6-a1:1.23
	core-8-4-19:1.5.2.8
	core-8-5-branch:1.23.0.2
	core-8-5-2:1.23
	core-8-4-18:1.5.2.8
	core-8-5-1:1.23
	core-8-4-17:1.5.2.8
	core-8-5-0:1.23
	core-8-5-b3:1.22
	core-8-5-b2:1.22
	core-8-4-16:1.5.2.8
	core-8-5-b1:1.22
	core-stablilizer-merge:1.22
	core-stabilizer-branch:1.21.0.2
	core-stabilizer-merge:1.23
	core-8-4-15:1.5.2.7
	core-8-5-a6:1.21
	core-8-5-a5:1.20
	core-8-4-14:1.5.2.6
	core-8-5-a4:1.19
	core-8-4-13:1.5.2.5
	core-8-4-12:1.5.2.4
	core-8-4-11:1.5.2.4
	core-8-5-a3:1.18
	core-8-4-10:1.5.2.4
	core-8-4-9-branch:1.5.2.3.0.2
	core-8-5-a2:1.17
	core-8-4-9:1.5.2.3
	core-8-4-8:1.5.2.3
	core-8-4-7:1.5.2.3
	core-8-5-a1:1.17
	core-8-4-6:1.5.2.3
	core-8-4-5:1.5.2.1
	mistachkin-dev-branch:1.5.0.4
	core-8-4-4:1.5
	core-8-4-3:1.5
	core-8-4-branch:1.5.0.2
	core-8-4-2:1.5
	core-8-4-1:1.4
	core-8-4-0:1.3
	macosx-8-4-merge-2002-08-31-trunk:1.2
	macosx-8-4-premerge-2002-08-31-branch:1.1.2.4
	macosx-8-4-merge-2002-08-30-branch:1.1.2.3
	macosx-8-4-merge-2002-08-20-branch:1.1.2.3
	macosx-premerge-6-9-02:1.1.2.1
	macosx-8-4-branch:1.1.0.2;
locks; strict;
comment	@ * @;


1.27
date	2009.12.16.22.00.30;	author nijtmans;	state Exp;
branches;
next	1.26;

1.26
date	2009.07.06.20.29.21;	author dkf;	state Exp;
branches;
next	1.25;

1.25
date	2009.06.29.14.35.01;	author das;	state Exp;
branches;
next	1.24;

1.24
date	2008.10.27.11.55.44;	author dkf;	state Exp;
branches;
next	1.23;

1.23
date	2007.12.13.15.27.10;	author dgp;	state Exp;
branches;
next	1.22;

1.22
date	2007.06.03.13.44.40;	author das;	state Exp;
branches;
next	1.21;

1.21
date	2007.04.23.21.24.33;	author das;	state Exp;
branches
	1.21.2.1;
next	1.20;

1.20
date	2006.07.21.06.26.28;	author das;	state Exp;
branches;
next	1.19;

1.19
date	2006.03.24.14.58.01;	author das;	state Exp;
branches;
next	1.18;

1.18
date	2005.05.14.20.48.15;	author das;	state Exp;
branches;
next	1.17;

1.17
date	2004.02.17.19.49.16;	author cc_benny;	state Exp;
branches;
next	1.16;

1.16
date	2004.02.14.16.32.39;	author cc_benny;	state Exp;
branches;
next	1.15;

1.15
date	2004.02.07.16.21.08;	author cc_benny;	state Exp;
branches;
next	1.14;

1.14
date	2004.01.25.12.03.59;	author cc_benny;	state Exp;
branches;
next	1.13;

1.13
date	2004.01.24.18.16.09;	author cc_benny;	state Exp;
branches;
next	1.12;

1.12
date	2003.12.15.19.32.17;	author cc_benny;	state Exp;
branches;
next	1.11;

1.11
date	2003.12.15.18.48.07;	author cc_benny;	state Exp;
branches;
next	1.10;

1.10
date	2003.12.15.16.47.12;	author cc_benny;	state Exp;
branches;
next	1.9;

1.9
date	2003.12.15.16.37.39;	author cc_benny;	state Exp;
branches;
next	1.8;

1.8
date	2003.12.15.16.15.44;	author cc_benny;	state Exp;
branches;
next	1.7;

1.7
date	2003.12.15.15.08.37;	author cc_benny;	state Exp;
branches;
next	1.6;

1.6
date	2003.11.20.12.40.15;	author cc_benny;	state Exp;
branches;
next	1.5;

1.5
date	2003.02.19.19.27.47;	author wolfsuit;	state Exp;
branches
	1.5.2.1;
next	1.4;

1.4
date	2002.10.16.11.29.50;	author vincentdarley;	state Exp;
branches;
next	1.3;

1.3
date	2002.09.09.23.52.02;	author hobbs;	state Exp;
branches;
next	1.2;

1.2
date	2002.08.31.06.12.30;	author das;	state Exp;
branches;
next	1.1;

1.1
date	2001.10.15.09.22.00;	author wolfsuit;	state dead;
branches
	1.1.2.1;
next	;

1.1.2.1
date	2001.10.15.09.22.00;	author wolfsuit;	state Exp;
branches;
next	1.1.2.2;

1.1.2.2
date	2002.07.18.23.45.18;	author vincentdarley;	state Exp;
branches;
next	1.1.2.3;

1.1.2.3
date	2002.07.19.09.22.34;	author vincentdarley;	state Exp;
branches;
next	1.1.2.4;

1.1.2.4
date	2002.08.30.18.18.16;	author das;	state Exp;
branches;
next	;

1.5.2.1
date	2003.11.21.13.05.09;	author cc_benny;	state Exp;
branches;
next	1.5.2.2;

1.5.2.2
date	2004.02.16.00.42.34;	author wolfsuit;	state Exp;
branches;
next	1.5.2.3;

1.5.2.3
date	2004.02.25.13.29.41;	author cc_benny;	state Exp;
branches;
next	1.5.2.4;

1.5.2.4
date	2005.05.14.20.53.31;	author das;	state Exp;
branches;
next	1.5.2.5;

1.5.2.5
date	2006.03.28.02.44.13;	author das;	state Exp;
branches;
next	1.5.2.6;

1.5.2.6
date	2006.07.21.06.26.54;	author das;	state Exp;
branches;
next	1.5.2.7;

1.5.2.7
date	2007.04.29.02.26.49;	author das;	state Exp;
branches;
next	1.5.2.8;

1.5.2.8
date	2007.06.04.09.28.45;	author das;	state Exp;
branches;
next	;

1.21.2.1
date	2007.06.04.15.19.00;	author dgp;	state Exp;
branches;
next	;


desc
@@


1.27
log
@CONSTify return values of TkKeysymToString,
TkFindStateString, TkpGetString, TkpGetChar,
which are all not supposed to be modified by
the caller. In tkUtil.c this gets rid of a
dangerous type cast.
@
text
@/*
 * tkMacOSXKeyboard.c --
 *
 *	Routines to support keyboard events on the Macintosh.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001-2009, Apple Inc.
 * Copyright (c) 2005-2009 Daniel A. Steffen <das@@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.26 2009/07/06 20:29:21 dkf Exp $
 */

#include "tkMacOSXPrivate.h"
#include "tkMacOSXEvent.h"

/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
 * tkMacOSXMouseEvent.c.
 */

#define LATIN1_MAX	 255
#define MAC_KEYCODE_MAX	 0x7F
#define MAC_KEYCODE_MASK 0x7F
#define COMMAND_MASK	 Mod1Mask
#define OPTION_MASK	 Mod2Mask


/*
 * Tables enumerating the special keys defined on Mac keyboards. These are
 * necessary for correct keysym mappings for all keys where the keysyms are
 * not identical with their ASCII or Latin-1 code points.
 */

typedef struct {
    int keycode;		/* Macintosh keycode. */
    KeySym keysym;		/* X windows keysym. */
} KeyInfo;

/*
 * Notes on keyArray:
 *
 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
 *
 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
 *
 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
 * applications don't use it like that, nor does Apple's X11.
 *
 * All other keycodes are taken from the published ADB keyboard layouts.
 */

static KeyInfo keyArray[] = {
    {0x24,	XK_Return},
    {0x30,	XK_Tab},
    {0x33,	XK_BackSpace},
    {0x34,	XK_Return},
    {0x35,	XK_Escape},

    {0x47,	XK_Clear},
    {0x4C,	XK_KP_Enter},

    {0x72,	XK_Help},
    {0x73,	XK_Home},
    {0x74,	XK_Page_Up},
    {0x75,	XK_Delete},
    {0x77,	XK_End},
    {0x79,	XK_Page_Down},

    {0x7B,	XK_Left},
    {0x7C,	XK_Right},
    {0x7D,	XK_Down},
    {0x7E,	XK_Up},

    {0,		0}
};

static KeyInfo virtualkeyArray[] = {
    {122,	XK_F1},
    {120,	XK_F2},
    {99,	XK_F3},
    {118,	XK_F4},
    {96,	XK_F5},
    {97,	XK_F6},
    {98,	XK_F7},
    {100,	XK_F8},
    {101,	XK_F9},
    {109,	XK_F10},
    {103,	XK_F11},
    {111,	XK_F12},
    {105,	XK_F13},
    {107,	XK_F14},
    {113,	XK_F15},
    {0,		0}
};

static int initialized = 0;
static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;		/* virtualkeyArray hashed by virtual
					 * keycode value. */

static int latin1Table[LATIN1_MAX+1];	/* Reverse mapping table for
					 * controls, ASCII and Latin-1. */

static int keyboardChanged = 1;

/*
 * Prototypes for static functions used in this file.
 */

static void	InitKeyMaps (void);
static void	InitLatin1Table(Display *display);
static int	XKeysymToMacKeycode(Display *display, KeySym keysym);
static int	KeycodeToUnicode(UniChar * uniChars, int maxChars,
			UInt16 keyaction, UInt32 keycode, UInt32 modifiers,
			UInt32 * deadKeyStatePtr);

#pragma mark TKApplication(TKKeyboard)

@@implementation TKApplication(TKKeyboard)
- (void) keyboardChanged: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
    TKLog(@@"-[%@@(%p) %s] %@@", [self class], self, _cmd, notification);
#endif
    keyboardChanged = 1;
}
@@end

#pragma mark -

/*
 *----------------------------------------------------------------------
 *
 * InitKeyMaps --
 *
 *	Creates hash tables used by some of the functions in this file.
 *
 *	FIXME: As keycodes are defined to be in the limited range 0-127, it
 *	would be easier and more efficient to use directly initialized plain
 *	arrays and drop this function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates memory & creates some hash tables.
 *
 *----------------------------------------------------------------------
 */

static void
InitKeyMaps(void)
{
    Tcl_HashEntry *hPtr;
    KeyInfo *kPtr;
    int dummy;

    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    initialized = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * InitLatin1Table --
 *
 *	Creates a simple table to be used for mapping from keysyms to keycodes.
 *	Always needs to be called before using latin1Table, because the
 *	keyboard layout may have changed, and than the table must be
 *	re-computed.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the global latin1Table.
 *
 *----------------------------------------------------------------------
 */

static void
InitLatin1Table(
    Display *display)
{
    int keycode;
    KeySym keysym;
    int state;
    int modifiers;

    memset(latin1Table, 0, sizeof(latin1Table));

    /*
     * In the common X11 implementations, a keymap has four columns
     * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We don't
     * use "Mode_switch", but we use "Option" instead. (This is similar to
     * Apple's X11 implementation, where "Mode_switch" is used as an alias
     * for "Option".)
     *
     * So here we go through all 4 columns of the keymap and find all
     * Latin-1 compatible keycodes. We go through the columns back-to-front
     * from the more exotic columns to the more simple, so that simple
     * keycode-modifier combinations are preferred in the resulting table.
     */

    for (state = 3; state >= 0; state--) {
	modifiers = 0;
	if (state & 1) {
	    modifiers |= shiftKey;
	}
	if (state & 2) {
	    modifiers |= optionKey;
	}

	for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
	    keysym = XKeycodeToKeysym(display,keycode<<16,state);
	    if (keysym <= LATIN1_MAX) {
		latin1Table[keysym] = keycode | modifiers;
	    }
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * KeycodeToUnicode --
 *
 *	Given MacOS key event data this function generates the Unicode
 *	characters. It does this using OS resources and APIs.
 *
 *	The parameter deadKeyStatePtr can be NULL, if no deadkey handling is
 *	needed.
 *
 *	This function is called from XKeycodeToKeysym() in tkMacOSKeyboard.c.
 *
 * Results:
 *	The number of characters generated if any, 0 if we are waiting for
 *	another byte of a dead-key sequence. Fills in the uniChars array with a
 *	Unicode string.
 *
 * Side Effects:
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
KeycodeToUnicode(
    UniChar *uniChars,
    int maxChars,
    UInt16 keyaction,
    UInt32 keycode,
    UInt32 modifiers,
    UInt32 *deadKeyStatePtr)
{
    static const void *uchr = NULL;
    static UInt32 keyboardType = 0;
    UniCharCount actuallength = 0;

    if (keyboardChanged) {
	TISInputSourceRef currentKeyboardLayout =
		TISCopyCurrentKeyboardLayoutInputSource();

	if (currentKeyboardLayout) {
	    CFDataRef keyLayoutData = (CFDataRef) TISGetInputSourceProperty(
		    currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData);

	    if (keyLayoutData) {
		uchr = CFDataGetBytePtr(keyLayoutData);
		keyboardType = LMGetKbdType();
	    }
	    CFRelease(currentKeyboardLayout);
	}
	keyboardChanged = 0;
    }
    if (uchr) {
	OptionBits options = 0;
	UInt32 dummyState;
	OSStatus err;

	keycode &= 0xFF;
	modifiers = (modifiers >> 8) & 0xFF;

	if (!deadKeyStatePtr) {
	    options = kUCKeyTranslateNoDeadKeysMask;
	    dummyState = 0;
	    deadKeyStatePtr = &dummyState;
	}

	err = ChkErr(UCKeyTranslate, uchr, keycode, keyaction, modifiers,
		keyboardType, options, deadKeyStatePtr, maxChars,
		&actuallength, uniChars);

	if (!actuallength && *deadKeyStatePtr) {
	    /*
	     * More data later
	     */

	    return 0;
	}
	*deadKeyStatePtr = 0;
	if (err != noErr) {
	    actuallength = 0;
	}
    }
    return actuallength;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeycodeToKeysym --
 *
 *	Translate from a system-dependent keycode to a system-independent
 *	keysym.
 *
 * Results:
 *	Returns the translated keysym, or NoSymbol on failure.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeySym
XKeycodeToKeysym(
    Display* display,
    KeyCode keycode,
    int index)
{
    register Tcl_HashEntry *hPtr;
    int newKeycode;
    UniChar newChar;

    (void) display; /*unused*/

    if (!initialized) {
	InitKeyMaps();
    }

    /*
     * When determining what keysym to produce we first check to see if the key
     * is a function key. We then check to see if the character is another
     * non-printing key. Finally, we return the key syms for all ASCII and
     * Latin-1 chars.
     */

    newKeycode = keycode >> 16;

    if ((keycode & 0xFFFF) >= 0xF700) { /* NSEvent.h function key unicodes */
	hPtr = Tcl_FindHashEntry(&vkeyTable, INT2PTR(newKeycode));
	if (hPtr != NULL) {
	    return (KeySym) Tcl_GetHashValue(hPtr);
	}
    }
    hPtr = Tcl_FindHashEntry(&keycodeTable, INT2PTR(newKeycode));
    if (hPtr != NULL) {
	return (KeySym) Tcl_GetHashValue(hPtr);
    }

    /*
     * Add in the Mac modifier flags for shift and option.
     */

    if (index & 1) {
	newKeycode |= shiftKey;
    }
    if (index & 2) {
	newKeycode |= optionKey;
    }

    newChar = 0;
    KeycodeToUnicode(&newChar, 1, kUCKeyActionDown, newKeycode & 0x00FF,
	    newKeycode & 0xFF00, NULL);

    /*
     * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up for
     * other characters for now.
     */

    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
	return newChar;
    }

    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetString --
 *
 *	Retrieve the string equivalent for the given keyboard event.
 *
 * Results:
 *	Returns the UTF string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

const char *
TkpGetString(
    TkWindow *winPtr,		/* Window where event occurred: Needed to get
				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    (void) winPtr; /*unused*/
    Tcl_DStringInit(dsPtr);
    return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
}

/*
 *----------------------------------------------------------------------
 *
 * XGetModifierMapping --
 *
 *	Fetch the current keycodes used as modifiers.
 *
 * Results:
 *	Returns a new modifier map.
 *
 * Side effects:
 *	Allocates a new modifier map data structure.
 *
 *----------------------------------------------------------------------
 */

XModifierKeymap *
XGetModifierMapping(
    Display *display)
{
    XModifierKeymap *modmap;

    (void) display; /*unused*/

    /*
     * MacOSX doesn't use the key codes for the modifiers for anything, and we
     * don't generate them either. So there is no modifier map.
     */

    modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
    modmap->max_keypermod = 0;
    modmap->modifiermap = NULL;
    return modmap;
}

/*
 *----------------------------------------------------------------------
 *
 * XFreeModifiermap --
 *
 *	Deallocate a modifier map that was created by XGetModifierMapping.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees the datastructure referenced by modmap.
 *
 *----------------------------------------------------------------------
 */

void
XFreeModifiermap(
    XModifierKeymap *modmap)
{
    if (modmap->modifiermap != NULL) {
	ckfree((char *) modmap->modifiermap);
    }
    ckfree((char *) modmap);
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString, XStringToKeysym --
 *
 *	These X window functions map keysyms to strings & strings to keysyms.
 *	However, Tk already does this for the most common keysyms. Therefore,
 *	these functions only need to support keysyms that will be specific to
 *	the Macintosh. Currently, there are none.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
XKeysymToString(
    KeySym keysym)
{
    return NULL;
}

KeySym
XStringToKeysym(
    const char* string)
{
    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToMacKeycode --
 *
 *	An internal function like XKeysymToKeycode but only generating the Mac
 *	specific keycode plus the modifiers Shift and Option.
 *
 * Results:
 *	A Mac keycode with the actual keycode in the low byte and Mac-style
 *	modifier bits in the high byte.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
XKeysymToMacKeycode(
    Display *display,
    KeySym keysym)
{
    KeyInfo *kPtr;

    if (keysym <= LATIN1_MAX) {
	/*
	 * Handle keysyms in the Latin-1 range where keysym and Unicode
	 * character code point are the same.
	 */

	if (keyboardChanged) {
	    InitLatin1Table(display);
	    keyboardChanged = 0;
	}
	return latin1Table[keysym];
    }

    /*
     * Handle special keys from our exception tables. Don't mind if this is
     * slow, neither the test suite nor [event generate] need to be optimized
     * (we hope).
     */

    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	if (kPtr->keysym == keysym) {
	    return kPtr->keycode;
	}
    }
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	if (kPtr->keysym == keysym) {
	    return kPtr->keycode;
	}
    }

    /*
     * For other keysyms (not Latin-1 and not special keys), we'd need a
     * generic keysym-to-unicode table. We don't have that, so we give up here.
     */

    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToKeycode --
 *
 *	The function XKeysymToKeycode takes an X11 keysym and converts it into
 *	a Mac keycode. It is in the stubs table for compatibility but not used
 *	anywhere in the core.
 *
 * Results:
 *	A 32 bit keycode with the the mac keycode (without modifiers) in the
 *	higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *	lower 8 bits of the keycode.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeyCode
XKeysymToKeycode(
    Display* display,
    KeySym keysym)
{
    int macKeycode = XKeysymToMacKeycode(display, keysym);
    KeyCode result;

    /*
     * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
     * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
     * the keysym are usually a related ASCII control code.
     */

    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
	result = 0x0010;
    } else {
	result = 0x00FF & keysym;
    }
    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;

    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpSetKeycodeAndState --
 *
 *	The function TkpSetKeycodeAndState takes a keysym and fills in the
 *	appropriate members of an XEvent. It is similar to XKeysymToKeycode,
 *	but it also sets the modifier mask in the XEvent. It is used by [event
 *	generate] and it is in the stubs table.
 *
 * Results:
 *	Fills an XEvent, sets the member xkey.keycode with a keycode
 *	formatted the same as XKeysymToKeycode and the member xkey.state with
 *	the modifiers implied by the keysym. Also fills in xkey.trans_chars,
 *	so that the actual characters can be retrieved later.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keysym,
    XEvent *eventPtr)
{
    if (keysym == NoSymbol) {
	eventPtr->xkey.keycode = 0;
    } else {
	Display *display = Tk_Display(tkwin);
	int macKeycode = XKeysymToMacKeycode(display, keysym);

	/*
	 * See also XKeysymToKeycode.
	 */

	if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
	    eventPtr->xkey.keycode = 0x0010;
	} else {
	    eventPtr->xkey.keycode = 0x00FF & keysym;
	}
	eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

	if (shiftKey & macKeycode) {
	    eventPtr->xkey.state |= ShiftMask;
	}
	if (optionKey & macKeycode) {
	    eventPtr->xkey.state |= OPTION_MASK;
	}

	if (keysym <= LATIN1_MAX) {
	    int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);

	    eventPtr->xkey.trans_chars[done] = 0;
	} else {
	    eventPtr->xkey.trans_chars[0] = 0;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetKeySym --
 *
 *	Given an X KeyPress or KeyRelease event, map the keycode in the event
 *	into a keysym.
 *
 * Results:
 *	The return value is the keysym corresponding to eventPtr, or NoSymbol
 *	if no matching keysym could be found.
 *
 * Side effects:
 *	In the first call for a given display, keycode-to-keysym maps get
 *	loaded.
 *
 *----------------------------------------------------------------------
 */

KeySym
TkpGetKeySym(
    TkDisplay *dispPtr,		/* Display in which to map keycode. */
    XEvent *eventPtr)		/* Description of X event. */
{
    KeySym sym;
    int index;

    /*
     * Refresh the mapping information if it's stale.
     */

    if (dispPtr->bindInfoStale) {
	TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Handle pure modifier keys specially. We use -1 as a signal for
     * this.
     */

    if (eventPtr->xany.send_event == -1) {
	int modifier = eventPtr->xkey.keycode;

	if (modifier == NSCommandKeyMask) {
	    return XK_Meta_L;
	} else if (modifier == NSShiftKeyMask) {
	    return XK_Shift_L;
	} else if (modifier == NSAlphaShiftKeyMask) {
	    return XK_Caps_Lock;
	} else if (modifier == NSAlternateKeyMask) {
	    return XK_Alt_L;
	} else if (modifier == NSControlKeyMask) {
	    return XK_Control_L;
	} else if (modifier == NSNumericPadKeyMask) {
	    return XK_Num_Lock;
	} else if (modifier == NSFunctionKeyMask) {
	    return XK_Super_L;
/*
	} else if (modifier == rightShiftKey) {
	    return XK_Shift_R;
	} else if (modifier == rightOptionKey) {
	    return XK_Alt_R;
	} else if (modifier == rightControlKey) {
	    return XK_Control_R;
*/
	} else {
	    /*
	     * If we get here, we probably need to implement something new.
	     */

	    return NoSymbol;
	}
    }

#if 0
    if (eventPtr->xkey.nbytes) {
	return eventPtr->xkey.nbytes;
    }
#endif

    /*
     * Figure out which of the four slots in the keymap vector to use for this
     * key. Refer to Xlib documentation for more info on how this computation
     * works. (Note: We use "Option" in keymap columns 2 and 3 where other
     * implementations have "Mode_switch".)
     */

    index = 0;

    /*
     * We want Option key combinations to use their base chars as keysyms, so
     * we ignore the option modifier here.
     */

#if 0
    if (eventPtr->xkey.state & OPTION_MASK) {
	index |= 2;
    }
#endif

    if ((eventPtr->xkey.state & ShiftMask)
	    || (/* (dispPtr->lockUsage != LU_IGNORE)
	    && */ (eventPtr->xkey.state & LockMask))) {
	index |= 1;
    }

    /*
     * First try of the actual translation.
     */

    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);

    /*
     * Special handling: If the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't upper-case
     * alphabetic, then switch back to the unshifted keysym.
     */

    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
	    /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {
	/*
	 * FIXME: Keysyms are only identical to Unicode for ASCII and Latin-1,
	 * so we can't use Tcl_UniCharIsUpper() for keysyms outside that range.
	 * This may be a serious problem here.
	 */

	if ((sym == NoSymbol) || (sym > LATIN1_MAX)
		|| !Tcl_UniCharIsUpper(sym)) {
	    index &= ~1;
	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    index);
	}
    }

    /*
     * Another bit of special handling: If this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		index & ~1);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitKeymapInfo --
 *
 *	This procedure is invoked to scan keymap information to recompute stuff
 *	that's important for binding, such as the modifier key (if any) that
 *	corresponds to the "Mode_switch" keysym.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Keymap-related information in dispPtr is updated.
 *
 *--------------------------------------------------------------
 */

void
TkpInitKeymapInfo(
    TkDisplay *dispPtr)		/* Display for which to recompute keymap
				 * information. */
{
    dispPtr->bindInfoStale = 0;

    /*
     * Behaviours that are variable on X11 are defined constant on MacOSX.
     * lockUsage is only used above in TkpGetKeySym(), nowhere else currently.
     * There is no offical "Mode_switch" key.
     */

    dispPtr->lockUsage = LU_CAPS;
    dispPtr->modeModMask = 0;

#if 0
    /*
     * With this, <Alt> and <Meta> become synonyms for <Command> and <Option>
     * in bindings like they are (and always have been) in the keysyms that
     * are reported by KeyPress events. But the init scripts like text.tcl
     * have some disabling bindings for <Meta>, so we don't want this without
     * some changes in those scripts. See also bug #700311.
     */

    dispPtr->altModMask = OPTION_MASK;
    dispPtr->metaModMask = COMMAND_MASK;
#else
    dispPtr->altModMask = 0;
    dispPtr->metaModMask = 0;
#endif

    /*
     * MacOSX doesn't use the keycodes for the modifiers for anything, and we
     * don't generate them either (the keycodes actually given in the simulated
     * modifier events are bogus). So there is no modifier map. If we ever want
     * to simulate real modifier keycodes, the list will be constant in the
     * Carbon implementation.
     */

    if (dispPtr->modKeyCodes != NULL) {
	ckfree((char *) dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    dispPtr->modKeyCodes = NULL;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
@


1.26
log
@More marking of files as Objective-C.
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.25 2009/06/29 14:35:01 das Exp $
d421 1
a421 1
char *
@


1.25
log
@Merge of TkAqua Cocoa port
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.24 2008/10/27 11:55:44 dkf Exp $
d125 2
a126 1
- (void)keyboardChanged:(NSNotification *)notification {
d910 1
a910 1
 * mode: c
@


1.24
log
@Code style improvements, especially including making code less deeply nested.
@
text
@d7 2
a8 2
 * Copyright 2001, Apple Computer, Inc.
 * Copyright (c) 2005-2007 Daniel A. Steffen <das@@users.sourceforge.net>
d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.23 2007/12/13 15:27:10 dgp Exp $
d16 2
a17 4
#include "tkMacOSXInt.h"
#include "tkMacOSXEvent.h"	/* for TkMacOSXKeycodeToUnicode()
				 * FIXME: That function should probably move
				 * here. */
d109 2
d118 14
d133 1
d164 1
a164 1
	hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
d170 1
a170 1
	hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
d200 61
a260 2
    static Boolean latin1_initialized = false;
    static SInt16 lastKeyLayoutID = -1;
d262 33
a294 2
    SInt16 keyScript;
    SInt16 keyLayoutID;
d296 2
a297 2
    keyScript = GetScriptManagerVariable(smKeyScript);
    keyLayoutID = GetScriptVariable(keyScript,smScriptKeys);
d299 5
a303 5
    if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) {
	int keycode;
	KeySym keysym;
	int state;
	int modifiers;
d305 3
a307 2
	latin1_initialized = true;
	lastKeyLayoutID = keyLayoutID;
d309 4
a312 1
	memset(latin1Table, 0, sizeof(latin1Table));
d314 5
a318 28
	/*
	 * In the common X11 implementations, a keymap has four columns
	 * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We don't
	 * use "Mode_switch", but we use "Option" instead. (This is similar to
	 * Apple's X11 implementation, where "Mode_switch" is used as an alias
	 * for "Option".)
	 *
	 * So here we go through all 4 columns of the keymap and find all
	 * Latin-1 compatible keycodes. We go through the columns back-to-front
	 * from the more exotic columns to the more simple, so that simple
	 * keycode-modifier combinations are preferred in the resulting table.
	 */

	for (state = 3; state >= 0; state--) {
	    modifiers = 0;
	    if (state & 1) {
		modifiers |= shiftKey;
	    }
	    if (state & 2) {
		modifiers |= optionKey;
	    }

	    for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
		keysym = XKeycodeToKeysym(display,keycode<<16,state);
		if (keysym <= LATIN1_MAX) {
		    latin1Table[keysym] = keycode | modifiers;
		}
	    }
d321 1
d366 2
a367 2
    if ((keycode & 0xFFFF) == 0x10) {
	hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
d372 1
a372 1
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode);
d389 2
a390 2
    TkMacOSXKeycodeToUnicode(&newChar, 1, kEventRawKeyDown,
	    newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d558 4
a561 1
	InitLatin1Table(display);
a632 26

/*
NB: Keep this commented code for a moment for reference.

    if ((keysym >= XK_space) && (XK_asciitilde)) {
	if (keysym == 'a') {
	    virtualKeyCode = 0x00;
	} else if (keysym == 'b' || keysym == 'B') {
	    virtualKeyCode = 0x0B;
	} else if (keysym == 'c') {
	    virtualKeyCode = 0x08;
	} else if (keysym == 'x' || keysym == 'X') {
	    virtualKeyCode = 0x07;
	} else if (keysym == 'z') {
	    virtualKeyCode = 0x06;
	} else if (keysym == ' ') {
	    virtualKeyCode = 0x31;
	} else if (keysym == XK_Return) {
	    virtualKeyCode = 0x24;
	    keysym = '\r';
	}
	keycode = keysym + (virtualKeyCode <<16);
    }

    return keycode;
*/
d739 1
a739 1
	if (modifier == cmdKey) {
d741 1
a741 1
	} else if (modifier == shiftKey) {
d743 1
a743 1
	} else if (modifier == alphaLock) {
d745 1
a745 1
	} else if (modifier == optionKey) {
d747 1
a747 1
	} else if (modifier == controlKey) {
d749 1
a749 1
	} else if (modifier == kEventKeyModifierNumLockMask) {
d751 1
a751 1
	} else if (modifier == kEventKeyModifierFnMask) {
d753 1
d760 1
d770 6
@


1.23
log
@merge stable branch onto HEAD
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.21.2.1 2007/06/04 15:19:00 dgp Exp $
d167 4
a170 4
 *	Creates a simple table to be used for mapping from keysyms to
 *	keycodes. Always needs to be called before using latin1Table,
 *	because the keyboard layout may have changed, and than the table must
 *	be re-computed.
d207 4
a210 4
	 * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We
	 * don't use "Mode_switch", but we use "Option" instead. (This is
	 * similar to Apple's X11 implementation, where "Mode_switch" is used
	 * as an alias for "Option".)
d213 3
a215 4
	 * Latin-1 compatible keycodes. We go through the columns
	 * back-to-front from the more exotic columns to the more simple, so
	 * that simple keycode-modifier combinations are preferred in the
	 * resulting table.
d271 4
a274 4
     * When determining what keysym to produce we first check to see if the
     * key is a function key. We then check to see if the character is
     * another non-printing key. Finally, we return the key syms for all
     * ASCII and Latin-1 chars.
d302 2
a303 3
    TkMacOSXKeycodeToUnicode(
	&newChar, 1, kEventRawKeyDown,
	newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d306 2
a307 2
     * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up
     * for other characters for now.
d364 1
a364 1
    Display* display)
d366 1
a366 1
    XModifierKeymap * modmap;
d371 2
a372 2
     * MacOSX doesn't use the key codes for the modifiers for anything, and
     * we don't generate them either. So there is no modifier map.
d413 3
a415 3
 *	However, Tk already does this for the most common keysyms.
 *	Therefore, these functions only need to support keysyms that will be
 *	specific to the Macintosh. Currently, there are none.
d445 2
a446 2
 *	An internal function like XKeysymToKeycode but only generating the
 *	Mac specific keycode plus the modifiers Shift and Option.
d463 2
a465 1

d473 1
d475 5
a479 1
    } else {
d481 3
a483 12
	/*
	 * Handle special keys from our exception tables. Don't mind if this
	 * is slow, neither the test suite nor [event generate] need to be
	 * optimized (we hope).
	 */

	KeyInfo *kPtr;

	for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	    if (kPtr->keysym == keysym) {
		return kPtr->keycode;
	    }
d485 4
a488 4
	for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	    if (kPtr->keysym == keysym) {
		return kPtr->keycode;
	    }
d490 1
d492 4
a495 5
	/*
	 * For other keysyms (not Latin-1 and not special keys), we'd need a
	 * generic keysym-to-unicode table. We don't have that, so we give
	 * up here.
	 */
d497 1
a497 2
	return 0;
    }
d505 3
a507 3
 *	The function XKeysymToKeycode takes an X11 keysym and converts it
 *	into a Mac keycode. It is in the stubs table for compatibility but
 *	not used anywhere in the core.
d577 2
a578 2
 *	but it also sets the modifier mask in the XEvent. It is used by
 *	[event generate] and it is in the stubs table.
d623 2
a624 2
	    int done;
	    done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
d674 1
a695 1

d705 4
a708 4
     * Figure out which of the four slots in the keymap vector to use for
     * this key. Refer to Xlib documentation for more info on how this
     * computation works. (Note: We use "Option" in keymap columns 2 and 3
     * where other implementations have "Mode_switch".)
d726 1
a726 1
		   && */ (eventPtr->xkey.state & LockMask))) {
d738 2
a739 2
     * only caps lock, not shift lock, and the shifted keysym isn't
     * upper-case alphabetic, then switch back to the unshifted keysym.
a743 1

d745 3
a747 3
	 * FIXME: Keysyms are only identical to Unicode for ASCII and
	 * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
	 * that range. This may be a serious problem here.
d775 3
a777 3
 *	This procedure is invoked to scan keymap information to recompute
 *	stuff that's important for binding, such as the modifier key (if any)
 *	that corresponds to the "Mode_switch" keysym.
d797 2
a798 2
     * lockUsage is only used above in TkpGetKeySym(), nowhere else
     * currently. There is no offical "Mode_switch" key.
d822 4
a825 4
     * don't generate them either (the keycodes actually given in the
     * simulated modifier events are bogus). So there is no modifier map.
     * If we ever want to simulate real modifier keycodes, the list will be
     * constant in the Carbon implementation.
d834 9
@


1.22
log
@	* macosx/tkMacOSXDraw.c:	comment formatting fix for Xcode 3.0.
	* macosx/tkMacOSXEmbed.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.21 2007/04/23 21:24:33 das Exp $
@


1.21
log
@	* macosx/tkMacOSXCarbonEvents.c: add window event target carbon event
	* macosx/tkMacOSXEvent.c:	 handler for all kEventClassWindow and
	* macosx/tkMacOSXEvent.h:	 kEventClassMouse events;
	* macosx/tkMacOSXNotify.c:	 move all remaining events except for
	* macosx/tkMacOSXWindowEvent.c:	 kEventClassKeyboard from dispatcher to
	application event handler; pass event handler callRef downstream; fix
	debug event tracing; process all tcl event types in carbon event timer;
	delay carbon event timer first fire; add TkMacOSXTrackingLoop() to mark
	enter/exit of event tracking loop during which all tcl events but only
	carbon update events should be processed by the timer (replaces various
	calls to Tcl_SetServiceMode()); rename TkMacOSXReceiveAndProcessEvent()
	to TkMacOSXReceiveAndDispatchEvent(), move it from tkMacOSXEvent.c to
	tkMacOSXCarbonEvents.c and modify it to dequeue only update events
	during a tracking loop; add TkMacOSXRunTclEventLoop() to standardize
	the various ways in use to run the tcl event loop; add handling of
	kEventClassAppearance events (for ScrollBarVariantChanged event).

	* macosx/tkMacOSXDialog.c:	use new TkMacOSXTrackingLoop() around
	* macosx/tkMacOSXEvent.c:	blocking API that puts up modal dialogs
	* macosx/tkMacOSXMenu.c:	or when entering/exiting menu/control
	* macosx/tkMacOSXMouseEvent.c:	tracking, window dragging and other
	* macosx/tkMacOSXScale.c:	mouse tracking loops.
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:

	* macosx/tkMacOSXDialog.c:	use new TkMacOSXRunTclEventLoop()
	* macosx/tkMacOSXScale.c:	instead of Tcl_DoOneEvent(),
	* macosx/tkMacOSXScrlbr.c:	Tcl_ServiceAll(), TclServiceIdle()
	* macosx/tkMacOSXWindowEvent.c:	and Tcl_GlobalEval("update idletasks").

	* macosx/tkMacOSXColor.c: make available as Tk system colors all
	* macosx/tkMacOSXPort.h:  appearance manager brushes, text colors and
	backgrounds with new and legacy names, as well as the fully transparent
	color "systemTransparent"; add TkMacOSXSetColorIn{Port,Context}() to
	directly set an X pixel color value in the current QD port resp. the
	given CG context without requiring passage through rgb representation
	(lossy for most system colors); modernize/remove Classic-era code;
	replace crufty strcmp() elseifs by Tcl_GetIndexFromObjStruct().

	* macosx/tkMacOSXButton.c:	use new TkMacOSXSetColorInPort()
	* macosx/tkMacOSXDraw.c:	instead of setting rgb color directly
	* macosx/tkMacOSXMenubutton.c:	to allow for non-rgb system colors.

	* macosx/tkMacOSXCursor.c: implement "none" cursor as on other
	platforms [Patch 1615427]; add all missing appearance manager cursors.

	* macosx/tkMacOSXDefault.h: set SELECT_FG_COLORs to None to match aqua
	L&F; use standard system color names; use new 'menu' system font;
	correct default scrollbar width.

	* macosx/tkMacOSXDraw.c:	standardize initialization, use and
	* macosx/tkMacOSXInt.h:		emptying of various static temp rgns
	* macosx/tkMacOSXRegion.c:	onto two global RgnHandles; in debug
	* macosx/tkMacOSXSubwindows.c:	builds, verify emptiness of these temp
	* macosx/tkMacOSXWindowEvent.c:	rgns before use.

	* macosx/tkMacOSXDraw.c: add TkMacOSX{Setup,Restore}DrawingContext() to
	* macosx/tkMacOSXInt.h:  abstract common setup & teardown of drawing
	environment (for both CG and QD); save/restore QD theme drawing state;
	handle GC clip region; add TkpClipDrawableToRect() to allow clipped
	drawing into drawable regardless of GC used; use new system color
	"systemWindowHeaderBackground" to setup background in themed toplevels;
	correct implementation of TkMacOSXMakeStippleMap().

	* macosx/tkMacOSXEntry.c:  use new TkMacOSXSetupDrawingContext() and
	* macosx/tkMacOSXFont.c:   TkMacOSXRestoreDrawingContext() instead of
	* macosx/ttkMacOSXTheme.c: various setup/teardown procs like
	TkMacOSX{SetUp,Release}CGContext(), TkMacOSXQuarz{Start,End}Draw(),
	TkMacOSXSetUpGraphicsPort() etc.

	* macosx/tkMacOSXEmbed.c: add CG context and drawable clip rgn fields
	* macosx/tkMacOSXInt.h:   to MacDrawable struct.
	* macosx/tkMacOSXSubwindows.c:

	* macosx/tkMacOSXDialog.c: make -parent option of tk_getOpenFile et al.
	use the sheet version of NavServices dialogs; ensure native parent win
	exists before using StandardSheet API for tk_messageBox [Bug 1677611];
	force sheets to behave like app-modal dialogs via WindowModality() API;
	use more modern ColorPicker API.

	* macosx/tkAboutDlg.r: use themed movable modal dialog, fix (c) year.

	* macosx/tkMacOSXEntry.c:  take xOff/yOff of MacDrawable into account
	* macosx/ttkMacOSXTheme.c: when computing locations/bounds to ensure
	correct posititioning when not drawing into intermediate pixmap.

	* macosx/tkMacOSXFont.c: use appearance manager API to map system font
	* macosx/tkMacOSXFont.h: names to TkFonts; add "menu" system font for
	menu item text drawing from MDEF; always draw with CG; remove QD
	dependent stippling algorithm; move most header declarations into the
	source file (as they were not used anywhere else).

	* macosx/tkMacOSXMenu.c:		 large-scale rewrite of custom
	* macosx/tkMacOSXMenu.r (removed):	 MDEF and related code that
	* macosx/Wish.xcode/project.pbxproj:	 restores many longtime-MIA
	* macosx/Wish.xcodeproj/project.pbxproj: features to working order
	* unix/Makefile.in:			 (e.g. images, custom colors &
	fonts in menus etc); implement compound menu items; use Appearance Mgr
	and ThemeText APIs to mimic native MDEF as closely as possible when
	default "menu" system font is used; remove now obsolete SICN drawing
	code and resources.

	* macosx/tkMacOSXCarbonEvents.c: handle additional menu carbon events
	* macosx/tkMacOSXEvent.c:	 in order to support <<MenuSelect>> in
	* macosx/tkMacOSXMenu.c:	 the menubar and in menus that are not
	* macosx/tkMacOSXMenus.c:	 using the custom MDEF [Bug 1620826];
	fix early and missing clearing of current Tk active menu entry; fix
	extraneous sending of <<MenuSelect>> during active menu entry clearing.

	* macosx/tkMacOSXMouseEvent.c: add support for async window dragging by
	the window server; set the corresponding window attribute by default.

	* macosx/tkMacOSXMouseEvent.c: rationalized handling order of
	non-mousedown events; add TkMacOSXModifierState() to retrieve the
	current key modifiers in carbon format.

	* macosx/tkMacOSXScrlbr.c: use appearance manager API to retrieve
	scrollbar component metrics; add awareness of multiple possibilites for
	scrollbar arrow position in aqua and handle user changes to arrow
	position pref; handle difference in metrics of small & large scrollbar
	variants; handle aqua "jump to here" scrollbar behaviour; correct
	computation of scroll view size and position; enforce min scrollbar
	height to avoid scrollbar component overlap; erase scrollbar area
	outside of standard width; remove broken auto-adjust code; account for
	window class when leaving space for grow box; remove code to manually
	draw grow box; use modern API for thumb scroll proc; replace
	HiliteControl() by modern API; replace control mgr constants with
	appearance mgr equivalents.

	* macosx/tkMacOSXSubwindows.c: use SetWindowBounds() API instead of
	SizeWindow(); invalidate clip regions after X{Map,Unmap}Window as fix
	for [Bug 940117] made them dependent on mapping state; remove unneeded
	calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port;
	use native-endian pixmap on intel; remove obsolete pixmap pix locking.

	* macosx/tkMacOSXWindowEvent.c: handle only the first of a batch of
	kEventAppAvailableWindowBoundsChanged events sent per transaction;
	handle kEventWindowBoundsChanged event to support live window resizing
	and centralized sending of location/size changed ConfigureNotify
	events; ensure HIGrowBox is redrawn after bounds change; constrain
	window after dragging to ensure titlebar is not inacessible
	offscreen or under dock/menubar; handle kEventWindowGetRegion and
	kEventWindowDrawContent for transparent windows to mark resp. paint
	content region as transparent; handle kEventWindowConstrain for
	fullscreen windows to ensure bounds match new screen size; enter/exit
	fullscreen UIMode upon activation/deactivation of fullscreen window.

	* macosx/tkMacOSXWm.c: use live-resize and async-drag carbon window
	* macosx/tkMacOSXWm.h: attributes for toplevels by default; implement
	new [wm attributes] -topmost, -transparent and -fullscreen; refactor
	WmAttributesCmd() parallelling the tkUnixWm.c implementation, use thus
	factored proc to set proxy icon from [wm iconbitmap]; dynamically
	determine default values for toplevel min and max sizes (similar to
	tkWinWm.c impl): min sizes depend on window class & attributes to
	ensure visibility of all titlebar widgets and grow box, max sizes
	depend on maximal window bounds for all active displays; factor out
	code that puts into effect changes to master or override_redirect; use
	RepositionWindow() API to determine staggered initial window bounds;
	correct resize limit calculations, handle gridding and use modern
	resize API in TkMacOSXGrowToplevel(); remove sending of ConfigureNotify
	after resize or zoom (now handled by BoundsChanged handler); correct
	composite carbon window attribute handling, remove currently unusable
	attributes and add new attributes in [tk::unsupported::MacWindowStyle];
	ensure validity of window class and attributes before use; apply
	changes to window class when handling carbon window attribute changes
	(if HIWindowChangeClass() API available); add debug build warning
	message when deprecated window style is used instead of window class;
	use transparent HIGrowBox for resizable windows; avoid unnecessary
	calls to window structure width API; use tcl time API in TkpGetMS();
	add TkMacOSXEnterExitFullscreen() to enter/exit UIMode with dock and
	menubar hidden; restrict wmTracing output to debug builds; remove
	unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD
	port; workaround GetWindowStructureWidths() Carbon bug (bogus results
	for never-mapped floating windows).

	* macosx/tkMacOSXXStubs.c (TkMacOSXDisplayChanged): add maximal window
	bounds field to Screen record (in ext_data), computed as the union of
	available window positioning bounds of all graphics devices (displays).

	* macosx/tkMacOSXBitmap.c: fix macRoman encoding leak.
	* macosx/tkMacOSXCursor.c:

	* macosx/tkMacOSXDebug.c (TkMacOSXCarbonEventToAscii): use static
	* macosx/tkMacOSXDebug.h: buffer to simplify callers; const fixes.

	* macosx/tkMacOSXBitmap.c: use more efficient QDSwapPort() instead of
	* macosx/tkMacOSXButton.c: GetPort()/SetPort()/GetGWorld()/SetGWorld().
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXScale.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXColor.c: use kHIToolboxVersionNumber for runtime OS
	* macosx/tkMacOSXEntry.c: version check rather than Gestalt() etc.
	* macosx/tkMacOSXInt.h:
	* macosx/tkMacOSXWm.c:

	* macosx/tkMacOSXDraw.c: remove obsolete and now incorrect
	* macosx/tkMacOSXInt.h:  tkMenuCascadeRgn clipping code.
	* macosx/tkMacOSXMenu.c:

	* macosx/tkMacOSXHLEvents.c: replace Tcl_GlobalEval() resp. Tcl_Eval()
	* macosx/tkMacOSXScrlbr.c:   by Tcl_EvalEx().
	* macosx/tkMacOSXInit.c:

	* macosx/tkMacOSXInit.c (TkpInit): reorder initialization steps.

	* macosx/tkMacOSXKeyEvent.c: remove pre-10.2 support.

	* macosx/tkMacOSXMenus.c: remove now useless call to
	TkMacOSXHandleTearoffMenu(); use \x.. quoting for non-latin1 macroman
	literar chars to allow file to be edited as utf-8.

	* macosx/tkMacOSXScale.c: replace TrackControl() by modern
	* macosx/tkMacOSXScrlbr.c: HandleControlClick() API (using new
	TkMacOSXModifierState()).

	* macosx/tkMacOSXInt.h:		move all constant #defines needed to
	* macosx/tkMacOSXColor.c:	support building on older OS X releases
	* macosx/tkMacOSXEvent.h:	to a central location in tkMacOSXInt.h.
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/ttkMacOSXTheme.c:

	* macosx/tkMacOSXInt.h:		 add ChkErr() macro to factor out
	* macosx/tkMacOSXButton.c:	 Carbon OSStatus return value checking
	* macosx/tkMacOSXCarbonEvents.c: and TkMacOSXDbgMsg() macro to factour
	* macosx/tkMacOSXClipboard.c:	 out debug message output; use these
	* macosx/tkMacOSXColor.c:	 macros to replace #ifdef TK_MAC_DEBUG
	* macosx/tkMacOSXCursor.c:	 blocks & direct printing to stderr,
	* macosx/tkMacOSXDebug.c:	 and to do additional OSStatus return
	* macosx/tkMacOSXDialog.c:	 checking, and to standardize OSStatus
	* macosx/tkMacOSXDraw.c:	 usage.
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXEvent.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXSend.c:	remove duplicate/unused declarations
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXDebug.c:	const fixes.
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXTest.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/Wish-Info.plist.in: add tcl document extensions/mime types and
	LSMinimumSystemVersion, LSRequiresCarbon & NSAppleScriptEnabled keys.

	* macosx/Wish-Common.xcconfig: add Wish's Info.plist as __info_plist
	section to tktest; enable more warnings.

	* macosx/Wish.xcodeproj/project.pbxproj: add 'DebugMemCompile' build
	configuration that calls configure with --enable-symbols=all; disable
	configure check for __attribute__((__visibility__("hidden"))) in Debug
	configuration to restore availability of ZeroLink.

	* macosx/Wish-Common.xcconfig:	fix whitespace.
	* macosx/Wish-Debug.xcconfig:
	* macosx/Wish-Release.xcconfig:
	* macosx/tkMacOSXAETE.r:
	* macosx/tkMacOSXConfig.c:
	* macosx/tkMacOSXCursors.r:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXSend.c:
	* macosx/ttkMacOSXTheme.c:
	* macosx/tkMacOSXXCursors.r:
	* macosx/README:

	* macosx/GNUmakefile:		fix/add copyright and license refs.
	* macosx/Tk-Info.plist.in:
	* macosx/Wish-Info.plist.in:
	* macosx/Wish.xcode/project.pbxproj:
	* macosx/Wish.xcodeproj/project.pbxproj:
	* macosx/tkMacOSX.h:
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.20 2006/07/21 06:26:28 das Exp $
d17 3
a19 2
#include "tkMacOSXEvent.h"	/* TkMacOSXKeycodeToUnicode() FIXME: That
				 * function should probably move here. */
@


1.21.2.1
log
@merge updates from HEAD
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.21 2007/04/23 21:24:33 das Exp $
d17 2
a18 3
#include "tkMacOSXEvent.h"	/* for TkMacOSXKeycodeToUnicode()
				 * FIXME: That function should probably move
				 * here. */
@


1.20
log
@	* generic/tkBind.c (TkBindInit): for REDO_KEYSYM_LOOKUP, change
	keysym-to-string mapping hash to use first name in ks_names.h instead of
	last (if there are multiple possibilities), e.g. "F11" instead of "L1".

	* macosx/tkMacOSXKeyboard.c (TkpGetKeySym): correct keysyms for pure
	modifier key presses [Bugs 700311, 1525905]; correct keysym for Enter
	key; add keysyms for new NumLock and Fn modifiers (added 2005-08-09).
@
text
@d1 1
a1 1
/* 
d4 1
a4 1
 *      Routines to support keyboard events on the Macintosh.
d8 1
d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.19 2006/03/24 14:58:01 das Exp $
d17 2
a18 2
#include "tkMacOSXEvent.h"      /* TkMacOSXKeycodeToUnicode() FIXME: That
                                 * function should probably move here. */
d27 2
a28 2
#define LATIN1_MAX       255
#define MAC_KEYCODE_MAX  0x7F
d30 2
a31 2
#define COMMAND_MASK     Mod1Mask
#define OPTION_MASK      Mod2Mask
d35 1
a35 1
 * Tables enumerating the special keys defined on Mac keyboards.  These are
d41 2
a42 2
    int keycode;                /* Macintosh keycode. */
    KeySym keysym;              /* X windows keysym. */
d59 20
a78 20
    {0x24,      XK_Return},
    {0x30,      XK_Tab},
    {0x33,      XK_BackSpace},
    {0x34,      XK_Return},
    {0x35,      XK_Escape},

    {0x47,      XK_Clear},
    {0x4C,      XK_KP_Enter},

    {0x72,      XK_Help},
    {0x73,      XK_Home},
    {0x74,      XK_Page_Up},
    {0x75,      XK_Delete},
    {0x77,      XK_End},
    {0x79,      XK_Page_Down},

    {0x7B,      XK_Left},
    {0x7C,      XK_Right},
    {0x7D,      XK_Down},
    {0x7E,      XK_Up},
d80 1
a80 1
    {0,         0}
d84 16
a99 16
    {122,       XK_F1},
    {120,       XK_F2},
    {99,        XK_F3},
    {118,       XK_F4},
    {96,        XK_F5},
    {97,        XK_F6},
    {98,        XK_F7},
    {100,       XK_F8},
    {101,       XK_F9},
    {109,       XK_F10},
    {103,       XK_F11},
    {111,       XK_F12},
    {105,       XK_F13},
    {107,       XK_F14},
    {113,       XK_F15},
    {0,         0}
d103 3
a105 3
static Tcl_HashTable keycodeTable;      /* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;         /* virtualkeyArray hashed by virtual
                                         * keycode value. */
d107 2
a108 2
static int latin1Table[LATIN1_MAX+1];   /* Reverse mapping table for
                                         * controls, ASCII and Latin-1.  */
d114 3
a116 3
static void     InitKeyMaps (void);
static void     InitLatin1Table(Display *display);
static int      XKeysymToMacKeycode(Display *display, KeySym keysym);
d124 1
a124 1
 *      Creates hash tables used by some of the functions in this file.
d126 3
a128 3
 *      FIXME: As keycodes are defined to be in the limited range 0-127, it
 *      would be easier and more efficient to use directly initialized plain
 *      arrays and drop this function.
d131 1
a131 1
 *      None.
d134 1
a134 1
 *      Allocates memory & creates some hash tables.
d140 1
a140 1
InitKeyMaps()
d145 1
a145 1
                
d148 3
a150 3
        hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
d154 3
a156 3
        hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
d166 4
a169 4
 *      Creates a simple table to be used for mapping from keysyms to
 *      keycodes.  Always needs to be called before using latin1Table,
 *      because the keyboard layout may have changed, and than the table must
 *      be re-computed.
d172 1
a172 1
 *      None.
d175 1
a175 1
 *      Sets the global latin1Table.
d194 40
a233 40
        int keycode;
        KeySym keysym;
        int state;
        int modifiers;

        latin1_initialized = true;
        lastKeyLayoutID = keyLayoutID;

        memset(latin1Table, 0, sizeof(latin1Table));
        
        /*
         * In the common X11 implementations, a keymap has four columns
         * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift".  We
         * don't use "Mode_switch", but we use "Option" instead.  (This is
         * similar to Apple's X11 implementation, where "Mode_switch" is used
         * as an alias for "Option".)
         *
         * So here we go through all 4 columns of the keymap and find all
         * Latin-1 compatible keycodes.  We go through the columns
         * back-to-front from the more exotic columns to the more simple, so
         * that simple keycode-modifier combinations are preferred in the
         * resulting table.
         */

        for (state = 3; state >= 0; state--) {
            modifiers = 0;
            if (state & 1) {
                modifiers |= shiftKey;
            }
            if (state & 2) {
                modifiers |= optionKey;
            }

            for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
                keysym = XKeycodeToKeysym(display,keycode<<16,state);
                if (keysym <= LATIN1_MAX) {
                    latin1Table[keysym] = keycode | modifiers;
                }
            }
        }
d242 2
a243 2
 *      Translate from a system-dependent keycode to a system-independent
 *      keysym.
d246 1
a246 1
 *      Returns the translated keysym, or NoSymbol on failure.
d249 1
a249 1
 *      None.
d254 1
a254 1
KeySym 
d267 1
a267 1
        InitKeyMaps();
d272 2
a273 2
     * key is a function key.  We then check to see if the character is
     * another non-printing key.  Finally, we return the key syms for all
d280 4
a283 4
        hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
        if (hPtr != NULL) {
            return (KeySym) Tcl_GetHashValue(hPtr);
        }
d287 1
a287 1
        return (KeySym) Tcl_GetHashValue(hPtr);
d290 1
a290 1
    /* 
d295 1
a295 1
        newKeycode |= shiftKey;
d298 1
a298 1
        newKeycode |= optionKey;
d303 2
a304 2
        &newChar, 1, kEventRawKeyDown,
        newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d307 1
a307 1
     * X11 keysyms are identical to Unicode for ASCII and Latin-1.  Give up
d312 1
a312 1
        return newChar;
d315 1
a315 1
    return NoSymbol; 
d323 1
a323 1
 *      Retrieve the string equivalent for the given keyboard event.
d326 1
a326 1
 *      Returns the UTF string.
d329 1
a329 1
 *      None.
d336 5
a340 5
    TkWindow *winPtr,           /* Window where event occurred: Needed to get
                                 * input context. */
    XEvent *eventPtr,           /* X keyboard event. */
    Tcl_DString *dsPtr)         /* Uninitialized or empty string to hold
                                 * result. */
d352 1
a352 1
 *      Fetch the current keycodes used as modifiers.
d355 1
a355 1
 *      Returns a new modifier map.
d358 1
a358 1
 *      Allocates a new modifier map data structure.
d363 1
a363 1
XModifierKeymap * 
d366 1
a366 1
{ 
d373 1
a373 1
     * we don't generate them either.  So there is no modifier map.
d387 1
a387 1
 *      Deallocate a modifier map that was created by XGetModifierMapping.
d390 1
a390 1
 *      None.
d393 1
a393 1
 *      Frees the datastructure referenced by modmap.
d398 1
a398 1
void 
d403 1
a403 1
        ckfree((char *) modmap->modifiermap);
d413 4
a416 4
 *      These X window functions map keysyms to strings & strings to keysyms.
 *      However, Tk already does this for the most common keysyms.
 *      Therefore, these functions only need to support keysyms that will be
 *      specific to the Macintosh.  Currently, there are none.
d419 1
a419 1
 *      None.
d422 1
a422 1
 *      None.
d427 1
a427 1
char * 
d431 1
a431 1
    return NULL; 
d434 1
a434 1
KeySym 
d437 1
a437 1
{ 
d446 2
a447 2
 *      An internal function like XKeysymToKeycode but only generating the
 *      Mac specific keycode plus the modifiers Shift and Option.
d450 2
a451 2
 *      A Mac keycode with the actual keycode in the low byte and Mac-style
 *      modifier bits in the high byte.
d454 1
a454 1
 *      None.
d466 4
a469 4
        /*
         * Handle keysyms in the Latin-1 range where keysym and Unicode
         * character code point are the same.
         */
d471 2
a472 2
        InitLatin1Table(display);
        return latin1Table[keysym];
d476 24
a499 24
        /*
         * Handle special keys from our exception tables.  Don't mind if this
         * is slow, neither the test suite nor [event generate] need to be
         * optimized (we hope).
         */

        KeyInfo *kPtr;
                
        for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }
        for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }

        /*
         * For other keysyms (not Latin-1 and not special keys), we'd need a
         * generic keysym-to-unicode table.  We don't have that, so we give
         * up here.
         */
d501 1
a501 1
        return 0;
d510 3
a512 3
 *      The function XKeysymToKeycode takes an X11 keysym and converts it
 *      into a Mac keycode.  It is in the stubs table for compatibility but
 *      not used anywhere in the core.
d515 3
a517 3
 *      A 32 bit keycode with the the mac keycode (without modifiers) in the
 *      higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *      lower 8 bits of the keycode.
d520 1
a520 1
 *      None.
d532 1
a532 1
    
d534 2
a535 2
     * See also TkpSetKeycodeAndState.  The 0x0010 magic is used in
     * XKeycodeToKeysym.  For special keys like XK_Return the lower 8 bits of
d540 1
a540 1
        result = 0x0010;
d542 1
a542 1
        result = 0x00FF & keysym;
d553 17
a569 17
        if (keysym == 'a') {
            virtualKeyCode = 0x00;
        } else if (keysym == 'b' || keysym == 'B') {
            virtualKeyCode = 0x0B;
        } else if (keysym == 'c') {
            virtualKeyCode = 0x08;
        } else if (keysym == 'x' || keysym == 'X') {
            virtualKeyCode = 0x07;
        } else if (keysym == 'z') {
            virtualKeyCode = 0x06;
        } else if (keysym == ' ') {
            virtualKeyCode = 0x31;
        } else if (keysym == XK_Return) {
            virtualKeyCode = 0x24;
            keysym = '\r';
        }
        keycode = keysym + (virtualKeyCode <<16);
d580 4
a583 4
 *      The function TkpSetKeycodeAndState takes a keysym and fills in the
 *      appropriate members of an XEvent.  It is similar to XKeysymToKeycode,
 *      but it also sets the modifier mask in the XEvent.  It is used by
 *      [event generate] and it is in the stubs table.
d586 4
a589 4
 *      Fills an XEvent, sets the member xkey.keycode with a keycode
 *      formatted the same as XKeysymToKeycode and the member xkey.state with
 *      the modifiers implied by the keysym.  Also fills in xkey.trans_chars,
 *      so that the actual characters can be retrieved later.
d592 1
a592 1
 *      None.
d604 1
a604 1
        eventPtr->xkey.keycode = 0;
d606 2
a607 2
        Display *display = Tk_Display(tkwin);
        int macKeycode = XKeysymToMacKeycode(display, keysym);
d609 25
a633 25
        /*
         * See also XKeysymToKeycode.
         */

        if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
            eventPtr->xkey.keycode = 0x0010;
        } else {
            eventPtr->xkey.keycode = 0x00FF & keysym;
        }
        eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

        if (shiftKey & macKeycode) {
            eventPtr->xkey.state |= ShiftMask;
        }
        if (optionKey & macKeycode) {
            eventPtr->xkey.state |= OPTION_MASK;
        }

        if (keysym <= LATIN1_MAX) {
            int done;
            done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
            eventPtr->xkey.trans_chars[done] = 0;
        } else {
            eventPtr->xkey.trans_chars[0] = 0;
        }
d642 2
a643 2
 *      Given an X KeyPress or KeyRelease event, map the keycode in the event
 *      into a keysym.
d646 2
a647 2
 *      The return value is the keysym corresponding to eventPtr, or NoSymbol
 *      if no matching keysym could be found.
d650 2
a651 2
 *      In the first call for a given display, keycode-to-keysym maps get
 *      loaded.
d658 2
a659 2
    TkDisplay *dispPtr,         /* Display in which to map keycode. */
    XEvent *eventPtr)           /* Description of X event. */
d669 1
a669 1
        TkpInitKeymapInfo(dispPtr);
d673 1
a673 1
     * Handle pure modifier keys specially.  We use -1 as a signal for
d678 26
a703 26
        int modifier = eventPtr->xkey.keycode;
        if (modifier == cmdKey) {
            return XK_Meta_L;
        } else if (modifier == shiftKey) {
            return XK_Shift_L;
        } else if (modifier == alphaLock) {
            return XK_Caps_Lock;
        } else if (modifier == optionKey) {
            return XK_Alt_L;
        } else if (modifier == controlKey) {
            return XK_Control_L;
        } else if (modifier == kEventKeyModifierNumLockMask) {
            return XK_Num_Lock;
        } else if (modifier == kEventKeyModifierFnMask) {
            return XK_Super_L;
        } else if (modifier == rightShiftKey) {
            return XK_Shift_R;
        } else if (modifier == rightOptionKey) {
            return XK_Alt_R;
        } else if (modifier == rightControlKey) {
            return XK_Control_R;
        } else {

            /*
             * If we get here, we probably need to implement something new.
             */
d705 2
a706 2
            return NoSymbol;
        } 
d711 2
a712 2
     * this key.  Refer to Xlib documentation for more info on how this
     * computation works.  (Note: We use "Option" in keymap columns 2 and 3
d725 1
a725 1
        index |= 2;
d730 3
a732 3
            || (/* (dispPtr->lockUsage != LU_IGNORE)
                   && */ (eventPtr->xkey.state & LockMask))) {
        index |= 1;
d748 1
a748 1
            /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {
d750 12
a761 12
        /*
         * FIXME: Keysyms are only identical to Unicode for ASCII and
         * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
         * that range.  This may be a serious problem here.
         */

        if ((sym == NoSymbol) || (sym > LATIN1_MAX)
                || !Tcl_UniCharIsUpper(sym)) {
            index &= ~1;
            sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                    index);
        }
d770 2
a771 2
        sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                index & ~1);
d781 3
a783 3
 *      This procedure is invoked to scan keymap information to recompute
 *      stuff that's important for binding, such as the modifier key (if any)
 *      that corresponds to the "Mode_switch" keysym.
d786 1
a786 1
 *      None.
d789 1
a789 1
 *      Keymap-related information in dispPtr is updated.
d796 2
a797 2
    TkDisplay *dispPtr)         /* Display for which to recompute keymap
                                 * information. */
d804 1
a804 1
     * currently.  There is no offical "Mode_switch" key.
d814 1
a814 1
     * are reported by KeyPress events.  But the init scripts like text.tcl
d816 1
a816 1
     * some changes in those scripts.  See also bug #700311.
d829 1
a829 1
     * simulated modifier events are bogus).  So there is no modifier map.
d835 1
a835 1
        ckfree((char *) dispPtr->modKeyCodes);
@


1.19
log
@	* generic/tkTextDisp.c:   moved #ifdef MAC_OSX_TK code added by
	* macosx/tkMacOSXColor.c: Patch #638966 into platform specific
	* macosx/tkMacOSXInt.h:   files.

	* macosx/tkMacOSX.h:             cleaned up & rationalized order of
	* macosx/tkMacOSXBitmap.c:       #includes of tk and carbon headers.
	* macosx/tkMacOSXButton.c:
	* macosx/tkMacOSXCarbonEvents.c:
	* macosx/tkMacOSXClipboard.c:
	* macosx/tkMacOSXColor.c:
	* macosx/tkMacOSXConfig.c:
	* macosx/tkMacOSXCursor.c:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXEmbed.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXEvent.c:
	* macosx/tkMacOSXEvent.h:
	* macosx/tkMacOSXFont.h:
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXInt.h:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXRegion.c:
	* macosx/tkMacOSXScale.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXWm.h:
	* macosx/tkMacOSXXStubs.c:
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.18 2005/05/14 20:48:15 das Exp $
d22 1
a22 1
 * For the assignments of Mod1==alt==command and Mod2==meta==option, see also
d29 1
a29 2
#undef ALT_MASK
#define ALT_MASK         Mod1Mask
d65 1
a65 1
    {0x4C,      XK_Return},
d679 1
a679 1
            return XK_Alt_L;
d685 1
a685 1
            return XK_Meta_L;
d688 4
d695 1
a695 1
            return XK_Meta_R;
d818 2
a819 2
    dispPtr->altModMask = ALT_MASK;
    dispPtr->metaModMask = OPTION_MASK;
@


1.18
log
@	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXNotify.c: introduction of new tcl notifier based on
	CFRunLoop allows replacement of the custom TkAqua notifier by a
	standard tcl event source. Removes requirement of threaded tcl core
	for TkAqua, allows to stub-link TkAqua against Tcl by removing use of
	the unstubbed TclInitNotifier & TclFinalizeNotifier. [Tcl Patch 1202052]

	* macosx/Wish.xcode/project.pbxproj:
	* macosx/Wish.pbproj/project.pbxproj: stub-link TkAqua: build with
	USE_TCL_STUBS and link against libtclstub instead of Tcl.framework,
	unexport libtclstub symbols from Tk to avoid duplicate symbol warnings
	when linking with both Tcl and Tk, fixes for gcc4.0 warnings.

	* macosx/Wish.xcode/project.pbxproj: sync with Wish.pbproj changes
	since 2004-11-19.
	NOTE: to use this project, need to uncomment the tclConfig.h settings
	at the top of tcl/unix/configure.in, autoconf and rebuild tcl !

	* macosx/tkMacOSXBitmap.c:
	* macosx/tkMacOSXButton.c:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c: fixed gcc 4.0 warnings.

	* unix/tcl.m4: sync with tcl
	* unix/configure: autoconf-2.59
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.17 2004/02/17 19:49:16 cc_benny Exp $
a14 4
#include "tkInt.h"
#include "X11/Xlib.h"
#include "X11/keysym.h"
#include <Carbon/Carbon.h>
@


1.17
log
@* (TkpInitKeymapInfo): Don't make <Alt> and <Meta> synonyms
  for <Command> and <Option> for now.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.16 2004/02/14 16:32:39 cc_benny Exp $
d33 1
@


1.16
log
@* Fix: Convert DOS lineends to Unix.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.15 2004/02/07 16:21:08 cc_benny Exp $
d808 10
d820 4
@


1.15
log
@* (TkpSetKeycodeAndState): Put UTF-8 into trans_chars instead
  of Latin-1.
@
text
@d1 824
a824 824
/* 
 * tkMacOSXKeyboard.c --
 *
 *      Routines to support keyboard events on the Macintosh.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001, Apple Computer, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.14 2004/01/25 12:03:59 cc_benny Exp $
 */

#include "tkInt.h"
#include "X11/Xlib.h"
#include "X11/keysym.h"
#include <Carbon/Carbon.h>
#include "tkMacOSXInt.h"
#include "tkMacOSXEvent.h"      /* TkMacOSXKeycodeToUnicode() FIXME: That
                                 * function should probably move here. */

/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==alt==command and Mod2==meta==option, see also
 * tkMacOSXMouseEvent.c.
 */

#define LATIN1_MAX       255
#define MAC_KEYCODE_MAX  0x7F
#define MAC_KEYCODE_MASK 0x7F
#define ALT_MASK         Mod1Mask
#define OPTION_MASK      Mod2Mask


/*
 * Tables enumerating the special keys defined on Mac keyboards.  These are
 * necessary for correct keysym mappings for all keys where the keysyms are
 * not identical with their ASCII or Latin-1 code points.
 */

typedef struct {
    int keycode;                /* Macintosh keycode. */
    KeySym keysym;              /* X windows keysym. */
} KeyInfo;

/*
 * Notes on keyArray:
 *
 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
 *
 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
 *
 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
 * applications don't use it like that, nor does Apple's X11.
 *
 * All other keycodes are taken from the published ADB keyboard layouts.
 */

static KeyInfo keyArray[] = {
    {0x24,      XK_Return},
    {0x30,      XK_Tab},
    {0x33,      XK_BackSpace},
    {0x34,      XK_Return},
    {0x35,      XK_Escape},

    {0x47,      XK_Clear},
    {0x4C,      XK_Return},

    {0x72,      XK_Help},
    {0x73,      XK_Home},
    {0x74,      XK_Page_Up},
    {0x75,      XK_Delete},
    {0x77,      XK_End},
    {0x79,      XK_Page_Down},

    {0x7B,      XK_Left},
    {0x7C,      XK_Right},
    {0x7D,      XK_Down},
    {0x7E,      XK_Up},

    {0,         0}
};

static KeyInfo virtualkeyArray[] = {
    {122,       XK_F1},
    {120,       XK_F2},
    {99,        XK_F3},
    {118,       XK_F4},
    {96,        XK_F5},
    {97,        XK_F6},
    {98,        XK_F7},
    {100,       XK_F8},
    {101,       XK_F9},
    {109,       XK_F10},
    {103,       XK_F11},
    {111,       XK_F12},
    {105,       XK_F13},
    {107,       XK_F14},
    {113,       XK_F15},
    {0,         0}
};

static int initialized = 0;
static Tcl_HashTable keycodeTable;      /* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;         /* virtualkeyArray hashed by virtual
                                         * keycode value. */

static int latin1Table[LATIN1_MAX+1];   /* Reverse mapping table for
                                         * controls, ASCII and Latin-1.  */

/*
 * Prototypes for static functions used in this file.
 */

static void     InitKeyMaps (void);
static void     InitLatin1Table(Display *display);
static int      XKeysymToMacKeycode(Display *display, KeySym keysym);


/*
 *----------------------------------------------------------------------
 *
 * InitKeyMaps --
 *
 *      Creates hash tables used by some of the functions in this file.
 *
 *      FIXME: As keycodes are defined to be in the limited range 0-127, it
 *      would be easier and more efficient to use directly initialized plain
 *      arrays and drop this function.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Allocates memory & creates some hash tables.
 *
 *----------------------------------------------------------------------
 */

static void
InitKeyMaps()
{
    Tcl_HashEntry *hPtr;
    KeyInfo *kPtr;
    int dummy;
                
    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
        hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
        hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    initialized = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * InitLatin1Table --
 *
 *      Creates a simple table to be used for mapping from keysyms to
 *      keycodes.  Always needs to be called before using latin1Table,
 *      because the keyboard layout may have changed, and than the table must
 *      be re-computed.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Sets the global latin1Table.
 *
 *----------------------------------------------------------------------
 */

static void
InitLatin1Table(
    Display *display)
{
    static Boolean latin1_initialized = false;
    static SInt16 lastKeyLayoutID = -1;

    SInt16 keyScript;
    SInt16 keyLayoutID;

    keyScript = GetScriptManagerVariable(smKeyScript);
    keyLayoutID = GetScriptVariable(keyScript,smScriptKeys);

    if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) {
        int keycode;
        KeySym keysym;
        int state;
        int modifiers;

        latin1_initialized = true;
        lastKeyLayoutID = keyLayoutID;

        memset(latin1Table, 0, sizeof(latin1Table));
        
        /*
         * In the common X11 implementations, a keymap has four columns
         * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift".  We
         * don't use "Mode_switch", but we use "Option" instead.  (This is
         * similar to Apple's X11 implementation, where "Mode_switch" is used
         * as an alias for "Option".)
         *
         * So here we go through all 4 columns of the keymap and find all
         * Latin-1 compatible keycodes.  We go through the columns
         * back-to-front from the more exotic columns to the more simple, so
         * that simple keycode-modifier combinations are preferred in the
         * resulting table.
         */

        for (state = 3; state >= 0; state--) {
            modifiers = 0;
            if (state & 1) {
                modifiers |= shiftKey;
            }
            if (state & 2) {
                modifiers |= optionKey;
            }

            for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
                keysym = XKeycodeToKeysym(display,keycode<<16,state);
                if (keysym <= LATIN1_MAX) {
                    latin1Table[keysym] = keycode | modifiers;
                }
            }
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XKeycodeToKeysym --
 *
 *      Translate from a system-dependent keycode to a system-independent
 *      keysym.
 *
 * Results:
 *      Returns the translated keysym, or NoSymbol on failure.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

KeySym 
XKeycodeToKeysym(
    Display* display,
    KeyCode keycode,
    int index)
{
    register Tcl_HashEntry *hPtr;
    int newKeycode;
    UniChar newChar;

    (void) display; /*unused*/

    if (!initialized) {
        InitKeyMaps();
    }

    /*
     * When determining what keysym to produce we first check to see if the
     * key is a function key.  We then check to see if the character is
     * another non-printing key.  Finally, we return the key syms for all
     * ASCII and Latin-1 chars.
     */

    newKeycode = keycode >> 16;

    if ((keycode & 0xFFFF) == 0x10) {
        hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
        if (hPtr != NULL) {
            return (KeySym) Tcl_GetHashValue(hPtr);
        }
    }
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode);
    if (hPtr != NULL) {
        return (KeySym) Tcl_GetHashValue(hPtr);
    }

    /* 
     * Add in the Mac modifier flags for shift and option.
     */

    if (index & 1) {
        newKeycode |= shiftKey;
    }
    if (index & 2) {
        newKeycode |= optionKey;
    }

    newChar = 0;
    TkMacOSXKeycodeToUnicode(
        &newChar, 1, kEventRawKeyDown,
        newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);

    /*
     * X11 keysyms are identical to Unicode for ASCII and Latin-1.  Give up
     * for other characters for now.
     */

    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
        return newChar;
    }

    return NoSymbol; 
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetString --
 *
 *      Retrieve the string equivalent for the given keyboard event.
 *
 * Results:
 *      Returns the UTF string.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

char *
TkpGetString(
    TkWindow *winPtr,           /* Window where event occurred: Needed to get
                                 * input context. */
    XEvent *eventPtr,           /* X keyboard event. */
    Tcl_DString *dsPtr)         /* Uninitialized or empty string to hold
                                 * result. */
{
    (void) winPtr; /*unused*/
    Tcl_DStringInit(dsPtr);
    return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
}

/*
 *----------------------------------------------------------------------
 *
 * XGetModifierMapping --
 *
 *      Fetch the current keycodes used as modifiers.
 *
 * Results:
 *      Returns a new modifier map.
 *
 * Side effects:
 *      Allocates a new modifier map data structure.
 *
 *----------------------------------------------------------------------
 */

XModifierKeymap * 
XGetModifierMapping(
    Display* display)
{ 
    XModifierKeymap * modmap;

    (void) display; /*unused*/

    /*
     * MacOSX doesn't use the key codes for the modifiers for anything, and
     * we don't generate them either.  So there is no modifier map.
     */

    modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
    modmap->max_keypermod = 0;
    modmap->modifiermap = NULL;
    return modmap;
}

/*
 *----------------------------------------------------------------------
 *
 * XFreeModifiermap --
 *
 *      Deallocate a modifier map that was created by XGetModifierMapping.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Frees the datastructure referenced by modmap.
 *
 *----------------------------------------------------------------------
 */

void 
XFreeModifiermap(
    XModifierKeymap *modmap)
{
    if (modmap->modifiermap != NULL) {
        ckfree((char *) modmap->modifiermap);
    }
    ckfree((char *) modmap);
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString, XStringToKeysym --
 *
 *      These X window functions map keysyms to strings & strings to keysyms.
 *      However, Tk already does this for the most common keysyms.
 *      Therefore, these functions only need to support keysyms that will be
 *      specific to the Macintosh.  Currently, there are none.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

char * 
XKeysymToString(
    KeySym keysym)
{
    return NULL; 
}

KeySym 
XStringToKeysym(
    const char* string)
{ 
    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToMacKeycode --
 *
 *      An internal function like XKeysymToKeycode but only generating the
 *      Mac specific keycode plus the modifiers Shift and Option.
 *
 * Results:
 *      A Mac keycode with the actual keycode in the low byte and Mac-style
 *      modifier bits in the high byte.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

static int
XKeysymToMacKeycode(
    Display *display,
    KeySym keysym)
{
    if (keysym <= LATIN1_MAX) {

        /*
         * Handle keysyms in the Latin-1 range where keysym and Unicode
         * character code point are the same.
         */

        InitLatin1Table(display);
        return latin1Table[keysym];

    } else {

        /*
         * Handle special keys from our exception tables.  Don't mind if this
         * is slow, neither the test suite nor [event generate] need to be
         * optimized (we hope).
         */

        KeyInfo *kPtr;
                
        for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }
        for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }

        /*
         * For other keysyms (not Latin-1 and not special keys), we'd need a
         * generic keysym-to-unicode table.  We don't have that, so we give
         * up here.
         */

        return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToKeycode --
 *
 *      The function XKeysymToKeycode takes an X11 keysym and converts it
 *      into a Mac keycode.  It is in the stubs table for compatibility but
 *      not used anywhere in the core.
 *
 * Results:
 *      A 32 bit keycode with the the mac keycode (without modifiers) in the
 *      higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *      lower 8 bits of the keycode.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

KeyCode
XKeysymToKeycode(
    Display* display,
    KeySym keysym)
{
    int macKeycode = XKeysymToMacKeycode(display, keysym);
    KeyCode result;
    
    /*
     * See also TkpSetKeycodeAndState.  The 0x0010 magic is used in
     * XKeycodeToKeysym.  For special keys like XK_Return the lower 8 bits of
     * the keysym are usually a related ASCII control code.
     */

    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
        result = 0x0010;
    } else {
        result = 0x00FF & keysym;
    }
    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;

    return result;
}

/*
NB: Keep this commented code for a moment for reference.

    if ((keysym >= XK_space) && (XK_asciitilde)) {
        if (keysym == 'a') {
            virtualKeyCode = 0x00;
        } else if (keysym == 'b' || keysym == 'B') {
            virtualKeyCode = 0x0B;
        } else if (keysym == 'c') {
            virtualKeyCode = 0x08;
        } else if (keysym == 'x' || keysym == 'X') {
            virtualKeyCode = 0x07;
        } else if (keysym == 'z') {
            virtualKeyCode = 0x06;
        } else if (keysym == ' ') {
            virtualKeyCode = 0x31;
        } else if (keysym == XK_Return) {
            virtualKeyCode = 0x24;
            keysym = '\r';
        }
        keycode = keysym + (virtualKeyCode <<16);
    }

    return keycode;
*/

/*
 *----------------------------------------------------------------------
 *
 * TkpSetKeycodeAndState --
 *
 *      The function TkpSetKeycodeAndState takes a keysym and fills in the
 *      appropriate members of an XEvent.  It is similar to XKeysymToKeycode,
 *      but it also sets the modifier mask in the XEvent.  It is used by
 *      [event generate] and it is in the stubs table.
 *
 * Results:
 *      Fills an XEvent, sets the member xkey.keycode with a keycode
 *      formatted the same as XKeysymToKeycode and the member xkey.state with
 *      the modifiers implied by the keysym.  Also fills in xkey.trans_chars,
 *      so that the actual characters can be retrieved later.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keysym,
    XEvent *eventPtr)
{
    if (keysym == NoSymbol) {
        eventPtr->xkey.keycode = 0;
    } else {
        Display *display = Tk_Display(tkwin);
        int macKeycode = XKeysymToMacKeycode(display, keysym);

        /*
         * See also XKeysymToKeycode.
         */

        if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
            eventPtr->xkey.keycode = 0x0010;
        } else {
            eventPtr->xkey.keycode = 0x00FF & keysym;
        }
        eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

        if (shiftKey & macKeycode) {
            eventPtr->xkey.state |= ShiftMask;
        }
        if (optionKey & macKeycode) {
            eventPtr->xkey.state |= OPTION_MASK;
        }

        if (keysym <= LATIN1_MAX) {
            int done;
            done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
            eventPtr->xkey.trans_chars[done] = 0;
        } else {
            eventPtr->xkey.trans_chars[0] = 0;
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetKeySym --
 *
 *      Given an X KeyPress or KeyRelease event, map the keycode in the event
 *      into a keysym.
 *
 * Results:
 *      The return value is the keysym corresponding to eventPtr, or NoSymbol
 *      if no matching keysym could be found.
 *
 * Side effects:
 *      In the first call for a given display, keycode-to-keysym maps get
 *      loaded.
 *
 *----------------------------------------------------------------------
 */

KeySym
TkpGetKeySym(
    TkDisplay *dispPtr,         /* Display in which to map keycode. */
    XEvent *eventPtr)           /* Description of X event. */
{
    KeySym sym;
    int index;

    /*
     * Refresh the mapping information if it's stale.
     */

    if (dispPtr->bindInfoStale) {
        TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Handle pure modifier keys specially.  We use -1 as a signal for
     * this.
     */

    if (eventPtr->xany.send_event == -1) {
        int modifier = eventPtr->xkey.keycode;
        if (modifier == cmdKey) {
            return XK_Alt_L;
        } else if (modifier == shiftKey) {
            return XK_Shift_L;
        } else if (modifier == alphaLock) {
            return XK_Caps_Lock;
        } else if (modifier == optionKey) {
            return XK_Meta_L;
        } else if (modifier == controlKey) {
            return XK_Control_L;
        } else if (modifier == rightShiftKey) {
            return XK_Shift_R;
        } else if (modifier == rightOptionKey) {
            return XK_Meta_R;
        } else if (modifier == rightControlKey) {
            return XK_Control_R;
        } else {

            /*
             * If we get here, we probably need to implement something new.
             */

            return NoSymbol;
        } 
    }

    /*
     * Figure out which of the four slots in the keymap vector to use for
     * this key.  Refer to Xlib documentation for more info on how this
     * computation works.  (Note: We use "Option" in keymap columns 2 and 3
     * where other implementations have "Mode_switch".)
     */

    index = 0;

    /*
     * We want Option key combinations to use their base chars as keysyms, so
     * we ignore the option modifier here.
     */

#if 0
    if (eventPtr->xkey.state & OPTION_MASK) {
        index |= 2;
    }
#endif

    if ((eventPtr->xkey.state & ShiftMask)
            || (/* (dispPtr->lockUsage != LU_IGNORE)
                   && */ (eventPtr->xkey.state & LockMask))) {
        index |= 1;
    }

    /*
     * First try of the actual translation.
     */

    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);

    /*
     * Special handling: If the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't
     * upper-case alphabetic, then switch back to the unshifted keysym.
     */

    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
            /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {

        /*
         * FIXME: Keysyms are only identical to Unicode for ASCII and
         * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
         * that range.  This may be a serious problem here.
         */

        if ((sym == NoSymbol) || (sym > LATIN1_MAX)
                || !Tcl_UniCharIsUpper(sym)) {
            index &= ~1;
            sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                    index);
        }
    }

    /*
     * Another bit of special handling: If this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
        sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                index & ~1);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitKeymapInfo --
 *
 *      This procedure is invoked to scan keymap information to recompute
 *      stuff that's important for binding, such as the modifier key (if any)
 *      that corresponds to the "Mode_switch" keysym.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Keymap-related information in dispPtr is updated.
 *
 *--------------------------------------------------------------
 */

void
TkpInitKeymapInfo(
    TkDisplay *dispPtr)         /* Display for which to recompute keymap
                                 * information. */
{
    dispPtr->bindInfoStale = 0;

    /*
     * Behaviours that are variable on X11 are defined constant on MacOSX.
     * lockUsage is only used above in TkpGetKeySym(), nowhere else
     * currently.  There is no offical "Mode_switch" key.
     */

    dispPtr->lockUsage = LU_CAPS;
    dispPtr->modeModMask = 0;
    dispPtr->altModMask = ALT_MASK;
    dispPtr->metaModMask = OPTION_MASK;

    /*
     * MacOSX doesn't use the keycodes for the modifiers for anything, and we
     * don't generate them either (the keycodes actually given in the
     * simulated modifier events are bogus).  So there is no modifier map.
     * If we ever want to simulate real modifier keycodes, the list will be
     * constant in the Carbon implementation.
     */

    if (dispPtr->modKeyCodes != NULL) {
        ckfree((char *) dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    dispPtr->modKeyCodes = NULL;
}
@


1.14
log
@* (TkpGetKeySym): Ignore option key for generation of keysym,
  as before.
@
text
@d1 824
a824 823
/* 
 * tkMacOSXKeyboard.c --
 *
 *      Routines to support keyboard events on the Macintosh.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001, Apple Computer, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.13 2004/01/24 18:16:09 cc_benny Exp $
 */

#include "tkInt.h"
#include "X11/Xlib.h"
#include "X11/keysym.h"
#include <Carbon/Carbon.h>
#include "tkMacOSXInt.h"
#include "tkMacOSXEvent.h"      /* TkMacOSXKeycodeToUnicode() FIXME: That
                                 * function should probably move here. */

/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==alt==command and Mod2==meta==option, see also
 * tkMacOSXMouseEvent.c.
 */

#define LATIN1_MAX       255
#define MAC_KEYCODE_MAX  0x7F
#define MAC_KEYCODE_MASK 0x7F
#define ALT_MASK         Mod1Mask
#define OPTION_MASK      Mod2Mask


/*
 * Tables enumerating the special keys defined on Mac keyboards.  These are
 * necessary for correct keysym mappings for all keys where the keysyms are
 * not identical with their ASCII or Latin-1 code points.
 */

typedef struct {
    int keycode;                /* Macintosh keycode. */
    KeySym keysym;              /* X windows keysym. */
} KeyInfo;

/*
 * Notes on keyArray:
 *
 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
 *
 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
 *
 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
 * applications don't use it like that, nor does Apple's X11.
 *
 * All other keycodes are taken from the published ADB keyboard layouts.
 */

static KeyInfo keyArray[] = {
    {0x24,      XK_Return},
    {0x30,      XK_Tab},
    {0x33,      XK_BackSpace},
    {0x34,      XK_Return},
    {0x35,      XK_Escape},

    {0x47,      XK_Clear},
    {0x4C,      XK_Return},

    {0x72,      XK_Help},
    {0x73,      XK_Home},
    {0x74,      XK_Page_Up},
    {0x75,      XK_Delete},
    {0x77,      XK_End},
    {0x79,      XK_Page_Down},

    {0x7B,      XK_Left},
    {0x7C,      XK_Right},
    {0x7D,      XK_Down},
    {0x7E,      XK_Up},

    {0,         0}
};

static KeyInfo virtualkeyArray[] = {
    {122,       XK_F1},
    {120,       XK_F2},
    {99,        XK_F3},
    {118,       XK_F4},
    {96,        XK_F5},
    {97,        XK_F6},
    {98,        XK_F7},
    {100,       XK_F8},
    {101,       XK_F9},
    {109,       XK_F10},
    {103,       XK_F11},
    {111,       XK_F12},
    {105,       XK_F13},
    {107,       XK_F14},
    {113,       XK_F15},
    {0,         0}
};

static int initialized = 0;
static Tcl_HashTable keycodeTable;      /* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;         /* virtualkeyArray hashed by virtual
                                         * keycode value. */

static int latin1Table[LATIN1_MAX+1];   /* Reverse mapping table for
                                         * controls, ASCII and Latin-1.  */

/*
 * Prototypes for static functions used in this file.
 */

static void     InitKeyMaps (void);
static void     InitLatin1Table(Display *display);
static int      XKeysymToMacKeycode(Display *display, KeySym keysym);


/*
 *----------------------------------------------------------------------
 *
 * InitKeyMaps --
 *
 *      Creates hash tables used by some of the functions in this file.
 *
 *      FIXME: As keycodes are defined to be in the limited range 0-127, it
 *      would be easier and more efficient to use directly initialized plain
 *      arrays and drop this function.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Allocates memory & creates some hash tables.
 *
 *----------------------------------------------------------------------
 */

static void
InitKeyMaps()
{
    Tcl_HashEntry *hPtr;
    KeyInfo *kPtr;
    int dummy;
                
    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
        hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
        hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    initialized = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * InitLatin1Table --
 *
 *      Creates a simple table to be used for mapping from keysyms to
 *      keycodes.  Always needs to be called before using latin1Table,
 *      because the keyboard layout may have changed, and than the table must
 *      be re-computed.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Sets the global latin1Table.
 *
 *----------------------------------------------------------------------
 */

static void
InitLatin1Table(
    Display *display)
{
    static Boolean latin1_initialized = false;
    static SInt16 lastKeyLayoutID = -1;

    SInt16 keyScript;
    SInt16 keyLayoutID;

    keyScript = GetScriptManagerVariable(smKeyScript);
    keyLayoutID = GetScriptVariable(keyScript,smScriptKeys);

    if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) {
        int keycode;
        KeySym keysym;
        int state;
        int modifiers;

        latin1_initialized = true;
        lastKeyLayoutID = keyLayoutID;

        memset(latin1Table, 0, sizeof(latin1Table));
        
        /*
         * In the common X11 implementations, a keymap has four columns
         * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift".  We
         * don't use "Mode_switch", but we use "Option" instead.  (This is
         * similar to Apple's X11 implementation, where "Mode_switch" is used
         * as an alias for "Option".)
         *
         * So here we go through all 4 columns of the keymap and find all
         * Latin-1 compatible keycodes.  We go through the columns
         * back-to-front from the more exotic columns to the more simple, so
         * that simple keycode-modifier combinations are preferred in the
         * resulting table.
         */

        for (state = 3; state >= 0; state--) {
            modifiers = 0;
            if (state & 1) {
                modifiers |= shiftKey;
            }
            if (state & 2) {
                modifiers |= optionKey;
            }

            for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
                keysym = XKeycodeToKeysym(display,keycode<<16,state);
                if (keysym <= LATIN1_MAX) {
                    latin1Table[keysym] = keycode | modifiers;
                }
            }
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XKeycodeToKeysym --
 *
 *      Translate from a system-dependent keycode to a system-independent
 *      keysym.
 *
 * Results:
 *      Returns the translated keysym, or NoSymbol on failure.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

KeySym 
XKeycodeToKeysym(
    Display* display,
    KeyCode keycode,
    int index)
{
    register Tcl_HashEntry *hPtr;
    int newKeycode;
    UniChar newChar;

    (void) display; /*unused*/

    if (!initialized) {
        InitKeyMaps();
    }

    /*
     * When determining what keysym to produce we first check to see if the
     * key is a function key.  We then check to see if the character is
     * another non-printing key.  Finally, we return the key syms for all
     * ASCII and Latin-1 chars.
     */

    newKeycode = keycode >> 16;

    if ((keycode & 0xFFFF) == 0x10) {
        hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
        if (hPtr != NULL) {
            return (KeySym) Tcl_GetHashValue(hPtr);
        }
    }
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode);
    if (hPtr != NULL) {
        return (KeySym) Tcl_GetHashValue(hPtr);
    }

    /* 
     * Add in the Mac modifier flags for shift and option.
     */

    if (index & 1) {
        newKeycode |= shiftKey;
    }
    if (index & 2) {
        newKeycode |= optionKey;
    }

    newChar = 0;
    TkMacOSXKeycodeToUnicode(
        &newChar, 1, kEventRawKeyDown,
        newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);

    /*
     * X11 keysyms are identical to Unicode for ASCII and Latin-1.  Give up
     * for other characters for now.
     */

    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
        return newChar;
    }

    return NoSymbol; 
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetString --
 *
 *      Retrieve the string equivalent for the given keyboard event.
 *
 * Results:
 *      Returns the UTF string.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

char *
TkpGetString(
    TkWindow *winPtr,           /* Window where event occurred: Needed to get
                                 * input context. */
    XEvent *eventPtr,           /* X keyboard event. */
    Tcl_DString *dsPtr)         /* Uninitialized or empty string to hold
                                 * result. */
{
    (void) winPtr; /*unused*/
    Tcl_DStringInit(dsPtr);
    return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
}

/*
 *----------------------------------------------------------------------
 *
 * XGetModifierMapping --
 *
 *      Fetch the current keycodes used as modifiers.
 *
 * Results:
 *      Returns a new modifier map.
 *
 * Side effects:
 *      Allocates a new modifier map data structure.
 *
 *----------------------------------------------------------------------
 */

XModifierKeymap * 
XGetModifierMapping(
    Display* display)
{ 
    XModifierKeymap * modmap;

    (void) display; /*unused*/

    /*
     * MacOSX doesn't use the key codes for the modifiers for anything, and
     * we don't generate them either.  So there is no modifier map.
     */

    modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
    modmap->max_keypermod = 0;
    modmap->modifiermap = NULL;
    return modmap;
}

/*
 *----------------------------------------------------------------------
 *
 * XFreeModifiermap --
 *
 *      Deallocate a modifier map that was created by XGetModifierMapping.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Frees the datastructure referenced by modmap.
 *
 *----------------------------------------------------------------------
 */

void 
XFreeModifiermap(
    XModifierKeymap *modmap)
{
    if (modmap->modifiermap != NULL) {
        ckfree((char *) modmap->modifiermap);
    }
    ckfree((char *) modmap);
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString, XStringToKeysym --
 *
 *      These X window functions map keysyms to strings & strings to keysyms.
 *      However, Tk already does this for the most common keysyms.
 *      Therefore, these functions only need to support keysyms that will be
 *      specific to the Macintosh.  Currently, there are none.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

char * 
XKeysymToString(
    KeySym keysym)
{
    return NULL; 
}

KeySym 
XStringToKeysym(
    const char* string)
{ 
    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToMacKeycode --
 *
 *      An internal function like XKeysymToKeycode but only generating the
 *      Mac specific keycode plus the modifiers Shift and Option.
 *
 * Results:
 *      A Mac keycode with the actual keycode in the low byte and Mac-style
 *      modifier bits in the high byte.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

static int
XKeysymToMacKeycode(
    Display *display,
    KeySym keysym)
{
    if (keysym <= LATIN1_MAX) {

        /*
         * Handle keysyms in the Latin-1 range where keysym and Unicode
         * character code point are the same.
         */

        InitLatin1Table(display);
        return latin1Table[keysym];

    } else {

        /*
         * Handle special keys from our exception tables.  Don't mind if this
         * is slow, neither the test suite nor [event generate] need to be
         * optimized (we hope).
         */

        KeyInfo *kPtr;
                
        for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }
        for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }

        /*
         * For other keysyms (not Latin-1 and not special keys), we'd need a
         * generic keysym-to-unicode table.  We don't have that, so we give
         * up here.
         */

        return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToKeycode --
 *
 *      The function XKeysymToKeycode takes an X11 keysym and converts it
 *      into a Mac keycode.  It is in the stubs table for compatibility but
 *      not used anywhere in the core.
 *
 * Results:
 *      A 32 bit keycode with the the mac keycode (without modifiers) in the
 *      higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *      lower 8 bits of the keycode.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

KeyCode
XKeysymToKeycode(
    Display* display,
    KeySym keysym)
{
    int macKeycode = XKeysymToMacKeycode(display, keysym);
    KeyCode result;
    
    /*
     * See also TkpSetKeycodeAndState.  The 0x0010 magic is used in
     * XKeycodeToKeysym.  For special keys like XK_Return the lower 8 bits of
     * the keysym are usually a related ASCII control code.
     */

    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
        result = 0x0010;
    } else {
        result = 0x00FF & keysym;
    }
    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;

    return result;
}

/*
NB: Keep this commented code for a moment for reference.

    if ((keysym >= XK_space) && (XK_asciitilde)) {
        if (keysym == 'a') {
            virtualKeyCode = 0x00;
        } else if (keysym == 'b' || keysym == 'B') {
            virtualKeyCode = 0x0B;
        } else if (keysym == 'c') {
            virtualKeyCode = 0x08;
        } else if (keysym == 'x' || keysym == 'X') {
            virtualKeyCode = 0x07;
        } else if (keysym == 'z') {
            virtualKeyCode = 0x06;
        } else if (keysym == ' ') {
            virtualKeyCode = 0x31;
        } else if (keysym == XK_Return) {
            virtualKeyCode = 0x24;
            keysym = '\r';
        }
        keycode = keysym + (virtualKeyCode <<16);
    }

    return keycode;
*/

/*
 *----------------------------------------------------------------------
 *
 * TkpSetKeycodeAndState --
 *
 *      The function TkpSetKeycodeAndState takes a keysym and fills in the
 *      appropriate members of an XEvent.  It is similar to XKeysymToKeycode,
 *      but it also sets the modifier mask in the XEvent.  It is used by
 *      [event generate] and it is in the stubs table.
 *
 * Results:
 *      Fills an XEvent, sets the member xkey.keycode with a keycode
 *      formatted the same as XKeysymToKeycode and the member xkey.state with
 *      the modifiers implied by the keysym.  Also fills in xkey.trans_chars,
 *      so that the actual characters can be retrieved later.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keysym,
    XEvent *eventPtr)
{
    if (keysym == NoSymbol) {
        eventPtr->xkey.keycode = 0;
    } else {
        Display *display = Tk_Display(tkwin);
        int macKeycode = XKeysymToMacKeycode(display, keysym);

        /*
         * See also XKeysymToKeycode.
         */

        if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
            eventPtr->xkey.keycode = 0x0010;
        } else {
            eventPtr->xkey.keycode = 0x00FF & keysym;
        }
        eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

        if (shiftKey & macKeycode) {
            eventPtr->xkey.state |= ShiftMask;
        }
        if (optionKey & macKeycode) {
            eventPtr->xkey.state |= OPTION_MASK;
        }

        if (keysym <= LATIN1_MAX) {
            eventPtr->xkey.trans_chars[0] = keysym;
            eventPtr->xkey.trans_chars[1] = 0;
        } else {
            eventPtr->xkey.trans_chars[0] = 0;
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetKeySym --
 *
 *      Given an X KeyPress or KeyRelease event, map the keycode in the event
 *      into a keysym.
 *
 * Results:
 *      The return value is the keysym corresponding to eventPtr, or NoSymbol
 *      if no matching keysym could be found.
 *
 * Side effects:
 *      In the first call for a given display, keycode-to-keysym maps get
 *      loaded.
 *
 *----------------------------------------------------------------------
 */

KeySym
TkpGetKeySym(
    TkDisplay *dispPtr,         /* Display in which to map keycode. */
    XEvent *eventPtr)           /* Description of X event. */
{
    KeySym sym;
    int index;

    /*
     * Refresh the mapping information if it's stale.
     */

    if (dispPtr->bindInfoStale) {
        TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Handle pure modifier keys specially.  We use -1 as a signal for
     * this.
     */

    if (eventPtr->xany.send_event == -1) {
        int modifier = eventPtr->xkey.keycode;
        if (modifier == cmdKey) {
            return XK_Alt_L;
        } else if (modifier == shiftKey) {
            return XK_Shift_L;
        } else if (modifier == alphaLock) {
            return XK_Caps_Lock;
        } else if (modifier == optionKey) {
            return XK_Meta_L;
        } else if (modifier == controlKey) {
            return XK_Control_L;
        } else if (modifier == rightShiftKey) {
            return XK_Shift_R;
        } else if (modifier == rightOptionKey) {
            return XK_Meta_R;
        } else if (modifier == rightControlKey) {
            return XK_Control_R;
        } else {

            /*
             * If we get here, we probably need to implement something new.
             */

            return NoSymbol;
        } 
    }

    /*
     * Figure out which of the four slots in the keymap vector to use for
     * this key.  Refer to Xlib documentation for more info on how this
     * computation works.  (Note: We use "Option" in keymap columns 2 and 3
     * where other implementations have "Mode_switch".)
     */

    index = 0;

    /*
     * We want Option key combinations to use their base chars as keysyms, so
     * we ignore the option modifier here.
     */

#if 0
    if (eventPtr->xkey.state & OPTION_MASK) {
        index |= 2;
    }
#endif

    if ((eventPtr->xkey.state & ShiftMask)
            || (/* (dispPtr->lockUsage != LU_IGNORE)
                   && */ (eventPtr->xkey.state & LockMask))) {
        index |= 1;
    }

    /*
     * First try of the actual translation.
     */

    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);

    /*
     * Special handling: If the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't
     * upper-case alphabetic, then switch back to the unshifted keysym.
     */

    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
            /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {

        /*
         * FIXME: Keysyms are only identical to Unicode for ASCII and
         * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
         * that range.  This may be a serious problem here.
         */

        if ((sym == NoSymbol) || (sym > LATIN1_MAX)
                || !Tcl_UniCharIsUpper(sym)) {
            index &= ~1;
            sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                    index);
        }
    }

    /*
     * Another bit of special handling: If this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
        sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                index & ~1);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitKeymapInfo --
 *
 *      This procedure is invoked to scan keymap information to recompute
 *      stuff that's important for binding, such as the modifier key (if any)
 *      that corresponds to the "Mode_switch" keysym.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Keymap-related information in dispPtr is updated.
 *
 *--------------------------------------------------------------
 */

void
TkpInitKeymapInfo(
    TkDisplay *dispPtr)         /* Display for which to recompute keymap
                                 * information. */
{
    dispPtr->bindInfoStale = 0;

    /*
     * Behaviours that are variable on X11 are defined constant on MacOSX.
     * lockUsage is only used above in TkpGetKeySym(), nowhere else
     * currently.  There is no offical "Mode_switch" key.
     */

    dispPtr->lockUsage = LU_CAPS;
    dispPtr->modeModMask = 0;
    dispPtr->altModMask = ALT_MASK;
    dispPtr->metaModMask = OPTION_MASK;

    /*
     * MacOSX doesn't use the keycodes for the modifiers for anything, and we
     * don't generate them either (the keycodes actually given in the
     * simulated modifier events are bogus).  So there is no modifier map.
     * If we ever want to simulate real modifier keycodes, the list will be
     * constant in the Carbon implementation.
     */

    if (dispPtr->modKeyCodes != NULL) {
        ckfree((char *) dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    dispPtr->modKeyCodes = NULL;
}
@


1.13
log
@* (TkpSetKeycodeAndState): Add setting of xkey.trans_chars.
  Now event.test works except event-double-click-drag-1.1.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.12 2003/12/15 19:32:17 cc_benny Exp $
d715 7
d725 2
@


1.12
log
@* (TkpSetKeycodeAndState): Don't clobber xkey.state.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.11 2003/12/15 18:48:07 cc_benny Exp $
d591 2
a592 1
 *      the modifiers implied by the keysym.
d629 7
@


1.11
log
@* (InitLatin1Table): Rename initialized to latin1_initialized
  to avoid confusion.  Actually set lastKeyLayoutID.  Use
  keycode<<16 for XKeycodeToKeysym.
* (XKeycodeToKeysym): Remove variables c and virtualKey,
  simplify code, don't special handle keycode == 0 (-> 'a').
* (XKeysymToMacKeycode): Add handling for function keys.  Use
  ASCII control codes instead of keysyms.
* (TkpSetKeycodeAndState): Ditto.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.10 2003/12/15 16:47:12 cc_benny Exp $
a606 1
        eventPtr->xkey.state = 0;
a621 1
        eventPtr->xkey.state = 0;
@


1.10
log
@* latin1Table, (InitLatin1Table): Add.
* (XKeysymToMacKeycode): Add.
* (XKeysymToKeycode): Use XKeysymToMacKeycode.
* (TkpSetKeycodeAndState): Ditto.
* (TkpSetKeycodeAndState): Adapt modifier flags handling.
* (TkpInitKeymapInfo): Update a comment.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.9 2003/12/15 16:37:39 cc_benny Exp $
d187 1
a187 1
    static Boolean initialized = false;
d196 1
a196 1
    if (!initialized || (lastKeyLayoutID != keyLayoutID)) {
d202 3
a204 1
        initialized = true;
d231 1
a231 1
                keysym = XKeycodeToKeysym(display,keycode,state);
a263 2
    int c;
    int virtualKey;
a272 16
    if (keycode == 0) {

        /* 
         * This means we had a pure modifier keypress or something similar
         * which is a TO DO.
         */

        return NoSymbol;
    }
    
    virtualKey = keycode >> 16;
    c = keycode & 0xFFFF;
    if (c > MAC_KEYCODE_MAX) {
        return NoSymbol;
    }

d280 4
a283 2
    if (c == 0x10) {
        hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
d288 1
a288 1
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
a296 1
    newKeycode = virtualKey;
d519 2
a520 1
 *      higher 16 bits and the keysym in the lower 16 bits.
d534 1
d537 3
a539 1
     * See also TkpSetKeycodeAndState.
d542 8
a549 1
    return (0xFFFF & keysym) | ((macKeycode & MAC_KEYCODE_MASK) << 16);
d616 6
a621 2
        eventPtr->xkey.keycode =
            (0xFFFF & keysym) | ((macKeycode & MAC_KEYCODE_MASK) << 16);
@


1.9
log
@* (TkpInitKeymapInfo): Remove dead code.  The code depended on
  the result of XGetModifierMapping, but that will always
  return an empty list.
* ALT_MASK, OPTION_MASK: Symbols for understanding the code
  better.
* (TkpSetKeycodeAndState): Hardcode Mode_switch == Option.
* (TkpGetKeySym): Ditto.
* (TkpGetKeySym): Comment lockUsage conditions, Mac OS X uses
  LU_CAPS always.
* (XKeycodeToKeysym): Handle option key in parameter index
  (only used by TkpGetKeySym).
* (TkpGetKeySym): Use Tcl_UniCharIsUpper, highlight problems
  with Latin1 limitation.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.8 2003/12/15 16:15:44 cc_benny Exp $
d32 1
d110 3
d118 2
d167 74
d462 64
d533 2
a534 2
 *      A 32 bit keycode with the the mac keycode but without modifiers in
 *      the higher 16 bits and the keysym in the lower 16 bits.
d547 1
a547 2
    KeyCode keycode = 0;
    char virtualKeyCode = 0;
d549 9
a557 1
    (void) display; /*unused*/
d580 1
a580 1
}
a608 6
    Display *display;
    int state;
    KeyCode keycode;
    
    display = Tk_Display(tkwin);
    
d610 2
a611 1
        keycode = 0;
d613 16
a628 13
        keycode = XKeysymToKeycode(display, keysym);
    }
    if (keycode != 0) {
        for (state = 0; state < 4; state++) {
            if (XKeycodeToKeysym(display, keycode, state) == keysym) {
                if (state & 1) {
                    eventPtr->xkey.state |= ShiftMask;
                }
                if (state & 2) {
                    eventPtr->xkey.state |= OPTION_MASK;
                }
                break;
            }
a630 1
    eventPtr->xkey.keycode = keycode;
d800 1
a800 1
     * constant on Carbon.
@


1.8
log
@* LATIN1_MAX and MAC_KEYCODE_MAX: Add and use for better
  maintainability.
* General comment on keyArray: Add.
* (XKeycodeToKeysym): Replace garbled comment.  Use symbols
  instead of magic constants.
* (TkpGetKeySym): Reorder computations to make this more
  logical.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.7 2003/12/15 15:08:37 cc_benny Exp $
d25 3
d32 2
d228 1
a228 1
     * Add in the Mac modifier flag for shift.
d235 3
d307 2
d406 2
d476 1
a476 4
                    TkDisplay *dispPtr;

                    dispPtr = ((TkWindow *) tkwin)->dispPtr; 
                    eventPtr->xkey.state |= dispPtr->modeModMask;
d561 1
a561 1
    if (eventPtr->xkey.state & dispPtr->modeModMask) {
d565 2
a566 2
            || ((dispPtr->lockUsage != LU_IGNORE)
                    && (eventPtr->xkey.state & LockMask))) {
d583 10
a592 4
            && (dispPtr->lockUsage == LU_CAPS)) {
        if (!(((sym >= XK_A) && (sym <= XK_Z))
                    || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
                    || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
a633 6
    XModifierKeymap *modMapPtr;
    KeyCode *codePtr;
    KeySym keysym;
    int count, i, j, max, arraySize;
#define KEYCODE_ARRAY_SIZE 20

a634 24
    modMapPtr = XGetModifierMapping(dispPtr->display);

    /*
     * Check the keycodes associated with the Lock modifier.  If any of them
     * is associated with the XK_Shift_Lock modifier, then Lock has to be
     * interpreted as Shift Lock, not Caps Lock.
     */

    dispPtr->lockUsage = LU_IGNORE;
    codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
    for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
        if (*codePtr == 0) {
            continue;
        }
        keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
        if (keysym == XK_Shift_Lock) {
            dispPtr->lockUsage = LU_SHIFT;
            break;
        }
        if (keysym == XK_Caps_Lock) {
            dispPtr->lockUsage = LU_CAPS;
            break;
        }
    }
d637 3
a639 3
     * Look through the keycodes associated with modifiers to see if the the
     * "mode switch", "meta", or "alt" keysyms are associated with any
     * modifiers.  If so, remember their modifier mask bits.
d642 1
d644 2
a645 19
    dispPtr->metaModMask = 0;
    dispPtr->altModMask = 0;
    codePtr = modMapPtr->modifiermap;
    max = 8*modMapPtr->max_keypermod;
    for (i = 0; i < max; i++, codePtr++) {
        if (*codePtr == 0) {
            continue;
        }
        keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
        if (keysym == XK_Mode_switch) {
            dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
        }
        if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
            dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
        }
        if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
            dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
        }
    }
d648 5
a652 1
     * Create an array of the keycodes for all modifier keys.
d659 1
a659 38
    arraySize = KEYCODE_ARRAY_SIZE;
    dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
            (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
        if (*codePtr == 0) {
            continue;
        }

        /*
         * Make sure that the keycode isn't already in the array.
         */

        for (j = 0; j < dispPtr->numModKeyCodes; j++) {
            if (dispPtr->modKeyCodes[j] == *codePtr) {
                goto nextModCode;
            }
        }
        if (dispPtr->numModKeyCodes >= arraySize) {
            KeyCode *new;

            /*
             * Ran out of space in the array; grow it.
             */

            arraySize *= 2;
            new = (KeyCode *) ckalloc((unsigned)
                    (arraySize * sizeof(KeyCode)));
            memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
                    (dispPtr->numModKeyCodes * sizeof(KeyCode)));
            ckfree((char *) dispPtr->modKeyCodes);
            dispPtr->modKeyCodes = new;
        }
        dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
        dispPtr->numModKeyCodes++;
    nextModCode:
        continue;
    }
    XFreeModifiermap(modMapPtr);
@


1.7
log
@* Comments: Add and clarify some points, correct spellings.
* Whitespace: Remove tabs, re-indent, re-wrap comments.
* keyArray: Reorder keys in logical groups.
* vituralkeyArray: Rename virtualkeyArray.
* Prototypes, function headers: Use ISO-C consistently.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.6 2003/11/20 12:40:15 cc_benny Exp $
d23 14
d182 2
d199 2
a200 2
    c = keycode & 0XFFFF;
    if (c > 255) {
d223 1
a223 2
     * Recompute the character based on the Shift key only.  TODO: The index
     * may also specify the NUM_LOCK.
d227 2
a228 2
    if (index & 0x01) {
        newKeycode += 0x0200;
d241 1
a241 1
    if ((newChar >= XK_space) && (newChar <= 0x255)) {
d512 2
a513 3
     * Figure out which of the four slots in the keymap vector to use for
     * this key.  Refer to Xlib documentation for more info on how this
     * computation works.
a515 9
    index = 0;
    if (eventPtr->xkey.state & dispPtr->modeModMask) {
        index = 2;
    }
    if ((eventPtr->xkey.state & ShiftMask)
            || ((dispPtr->lockUsage != LU_IGNORE)
                    && (eventPtr->xkey.state & LockMask))) {
        index += 1;
    }
a516 5

        /*
         * We use -1 as a special signal for a pure modifier.
         */

d543 22
@


1.6
log
@* keyArray: Add 0x34 as <Return>.  Add notes.
@
text
@d4 1
a4 1
 *	Routines to support keyboard events on the Macintosh.
d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5 2003/02/19 19:27:47 wolfsuit Exp $
d21 1
a21 1
                                 * function should probably move here */
d24 2
a25 2
    int keycode;		/* Macintosh keycode */
    KeySym keysym;		/* X windows Keysym */
d33 2
d36 1
a36 1
 * applications don't use it like that.
d42 22
a63 18
    {0x4C,	XK_Return},
    {0x24,	XK_Return},
    {0x34,  XK_Return},
    {0x33,	XK_BackSpace},
    {0x75,	XK_Delete},
    {0x30,	XK_Tab},
    {0x74,	XK_Page_Up},
    {0x79,	XK_Page_Down},
    {0x73,	XK_Home},
    {0x77,	XK_End},
    {0x7B,	XK_Left},
    {0x7C,	XK_Right},
    {0x7E,	XK_Up},
    {0x7D,	XK_Down},
    {0x72,	XK_Help},
    {0x35,	XK_Escape},
    {0x47,	XK_Clear},
    {0,		0}
d66 17
a82 17
static KeyInfo vituralkeyArray[] = {
    {122,	XK_F1},
    {120,	XK_F2},
    {99,	XK_F3},
    {118,	XK_F4},
    {96,	XK_F5},
    {97,	XK_F6},
    {98,	XK_F7},
    {100,	XK_F8},
    {101,	XK_F9},
    {109,	XK_F10},
    {103,	XK_F11},
    {111,	XK_F12},
    {105,	XK_F13},
    {107,	XK_F14},
    {113,	XK_F15},
    {0,		0}
d86 3
a88 3
static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;		/* vituralkeyArray hashed by virtual
					   keycode value. */
d93 2
a94 1
static void	InitKeyMaps _ANSI_ARGS_((void));
d102 5
a106 1
 *	Creates hash tables used by some of the functions in this file.
d109 1
a109 1
 *	None.
d112 1
a112 1
 *	Allocates memory & creates some hash tables.
d123 1
a123 1
		
d126 3
a128 3
	hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
d131 4
a134 4
    for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
d144 2
a145 2
 *	Translate from a system-dependent keycode to a
 *	system-independent keysym.
d148 1
a148 1
 *	Returns the translated keysym, or NoSymbol on failure.
d151 1
a151 1
 *	None.
d160 1
a160 1
    int	index)
d169 1
a169 1
	InitKeyMaps();
d171 1
d173 1
d175 2
a176 2
         * This means we had a pure modifier keypress or
         * something similar which is a TO DO.
d178 1
d183 1
a183 1
    c = (keycode) & 0xffff;
d189 4
a192 4
     * When determining what keysym to produce we first check to see if
     * the key is a function key.  We then check to see if the character
     * is another non-printing key.  Finally, we return the key syms
     * for all ASCII chars.
d194 1
d196 2
a197 2
	hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
	if (hPtr != NULL) {
d199 1
a199 1
	}
d203 1
a203 1
 	return (KeySym) Tcl_GetHashValue(hPtr);
d207 2
a208 2
     * Recompute the character based on the Shift key only.
     * TODO: The index may also specify the NUM_LOCK.
d210 1
d213 1
a213 1
	newKeycode += 0x0200;
d218 2
a219 2
            &newChar, 1, kEventRawKeyDown,
            newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d225 3
a227 2
    if (newChar >= XK_space && newChar <= 0x255) {
  	return newChar;
d238 1
a238 1
 *	Retrieve the string equivalent for the given keyboard event.
d241 1
a241 1
 *	Returns the UTF string.
d244 1
a244 1
 *	None.
d251 5
a255 5
    TkWindow *winPtr,		/* Window where event occurred:  needed to
				 * get input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
d267 1
a267 1
 *	Fetch the current keycodes used as modifiers.
d270 1
a270 1
 *	Returns a new modifier map.
d273 1
a273 1
 *	Allocates a new modifier map data structure.
d284 5
d300 1
a300 2
 *	Deallocate a modifier map that was created by
 *	XGetModifierMapping.
d303 1
a303 1
 *	None.
d306 1
a306 1
 *	Frees the datastructure referenced by modmap.
d316 1
a316 1
	ckfree((char *) modmap->modifiermap);
d326 4
a329 4
 *	These X window functions map Keysyms to strings & strings to 
 * 	keysyms.  However, Tk already does this for the most common keysyms.  
 *  	Therefor, these functions only need to support keysyms that will be 
 *  	specific to the Macintosh.  Currently, there are none.
d332 1
a332 1
 *	None.
d335 1
a335 1
 *	None.
d349 1
a349 1
    const char*	string)
d359 3
a361 5
 *	The function XKeysymToKeycode is only used by tkTest.c and
 *	currently only implementes the support for keys used in the
 *	Tk test suite.
 *      FIXME - This is no longer true.  This function is now used in
 *      "event generate" so we really should make it work.
d364 2
a365 1
 *	None.
d368 1
a368 1
 *	None.
d398 1
a398 1
	keycode = keysym + (virtualKeyCode <<16);
d405 18
a422 5
 * When mapping from a keysym to a keycode, need
 * information about the modifier state that should be used
 * so that when they call XKeycodeToKeysym taking into
 * account the xkey.state, they will get back the original
 * keysym.
d426 4
a429 4
TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
    Tk_Window tkwin;
    KeySym keySym;
    XEvent *eventPtr;
d437 2
a438 2
    if (keySym == NoSymbol) {
	keycode = 0;
d440 1
a440 1
	keycode = XKeysymToKeycode(display, keySym);
d443 14
a456 14
	for (state = 0; state < 4; state++) {
	    if (XKeycodeToKeysym(display, keycode, state) == keySym) {
		if (state & 1) {
		    eventPtr->xkey.state |= ShiftMask;
		}
		if (state & 2) {
		    TkDisplay *dispPtr;

		    dispPtr = ((TkWindow *) tkwin)->dispPtr; 
		    eventPtr->xkey.state |= dispPtr->modeModMask;
		}
		break;
	    }
	}
d466 2
a467 2
 *	Given an X KeyPress or KeyRelease event, map the
 *	keycode in the event into a KeySym.
d470 2
a471 3
 *	The return value is the KeySym corresponding to
 *	eventPtr, or NoSymbol if no matching Keysym could be
 *	found.
d474 2
a475 2
 *	In the first call for a given display, keycode-to-
 *	KeySym maps get loaded.
d481 3
a483 4
TkpGetKeySym(dispPtr, eventPtr)
    TkDisplay *dispPtr;	/* Display in which to
					 * map keycode. */
    XEvent *eventPtr;		/* Description of X event. */
d489 1
a489 1
     * Refresh the mapping information if it's stale
d493 1
a493 1
	TkpInitKeymapInfo(dispPtr);
d497 3
a499 3
     * Figure out which of the four slots in the keymap vector to
     * use for this key.  Refer to Xlib documentation for more info
     * on how this computation works.
d504 1
a504 1
	index = 2;
d507 3
a509 3
	    || ((dispPtr->lockUsage != LU_IGNORE)
	    && (eventPtr->xkey.state & LockMask))) {
	index += 1;
d512 30
a541 22
	/* We use -1 as a special signal for a pure modifier */
	int modifier = eventPtr->xkey.keycode;
	if (modifier == cmdKey) {
	    return XK_Alt_L;
	} else if (modifier == shiftKey) {
	    return XK_Shift_L;
	} else if (modifier == alphaLock) {
	    return XK_Caps_Lock;
	} else if (modifier == optionKey) {
	    return XK_Meta_L;
	} else if (modifier == controlKey) {
	    return XK_Control_L;
	} else if (modifier == rightShiftKey) {
	    return XK_Shift_R;
	} else if (modifier == rightOptionKey) {
	    return XK_Meta_R;
	} else if (modifier == rightControlKey) {
	    return XK_Control_R;
	} else {
	    /* If we get here, we probably need to implement something new */
	    return NoSymbol;
	} 
d546 3
a548 4
     * Special handling:  if the key was shifted because of Lock, but
     * lock is only caps lock, not shift lock, and the shifted keysym
     * isn't upper-case alphabetic, then switch back to the unshifted
     * keysym.
d552 8
a559 8
	    && (dispPtr->lockUsage == LU_CAPS)) {
	if (!(((sym >= XK_A) && (sym <= XK_Z))
		|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
		|| ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
	    index &= ~1;
	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    index);
	}
d563 2
a564 2
     * Another bit of special handling:  if this is a shifted key and there
     * is no keysym defined, then use the keysym for the unshifted key.
d568 2
a569 2
	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		index & ~1);
d579 3
a581 4
 *	This procedure is invoked to scan keymap information
 *	to recompute stuff that's important for binding, such
 *	as the modifier key (if any) that corresponds to "mode
 *	switch".
d584 1
a584 1
 *	None.
d587 1
a587 1
 *	Keymap-related information in dispPtr is updated.
d593 3
a595 3
TkpInitKeymapInfo(dispPtr)
    TkDisplay *dispPtr;		/* Display for which to recompute keymap
				 * information. */
d607 3
a609 3
     * Check the keycodes associated with the Lock modifier.  If
     * any of them is associated with the XK_Shift_Lock modifier,
     * then Lock has to be interpreted as Shift Lock, not Caps Lock.
d615 12
a626 12
	if (*codePtr == 0) {
	    continue;
	}
	keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
	if (keysym == XK_Shift_Lock) {
	    dispPtr->lockUsage = LU_SHIFT;
	    break;
	}
	if (keysym == XK_Caps_Lock) {
	    dispPtr->lockUsage = LU_CAPS;
	    break;
	}
d630 3
a632 3
     * Look through the keycodes associated with modifiers to see if
     * the the "mode switch", "meta", or "alt" keysyms are associated
     * with any modifiers.  If so, remember their modifier mask bits.
d641 13
a653 13
	if (*codePtr == 0) {
	    continue;
	}
	keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
	if (keysym == XK_Mode_switch) {
	    dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
	    dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
	    dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
d661 1
a661 1
	ckfree((char *) dispPtr->modKeyCodes);
d666 1
a666 1
	    (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
d668 32
a699 31
	if (*codePtr == 0) {
	    continue;
	}

	/*
	 * Make sure that the keycode isn't already in the array.
	 */

	for (j = 0; j < dispPtr->numModKeyCodes; j++) {
	    if (dispPtr->modKeyCodes[j] == *codePtr) {
		goto nextModCode;
	    }
	}
	if (dispPtr->numModKeyCodes >= arraySize) {
	    KeyCode *new;

	    /*
	     * Ran out of space in the array;  grow it.
	     */

	    arraySize *= 2;
	    new = (KeyCode *) ckalloc((unsigned)
		    (arraySize * sizeof(KeyCode)));
	    memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
		    (dispPtr->numModKeyCodes * sizeof(KeyCode)));
	    ckfree((char *) dispPtr->modKeyCodes);
	    dispPtr->modKeyCodes = new;
	}
	dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
	dispPtr->numModKeyCodes++;
	nextModCode: continue;
@


1.5
log
@This submission contains a slightly reworked & cleaned up version of
two parts of the patches in Patch Tracker #622582 -
new-evthdlng.2003-02-12.diff and basic-keyboard.2003-02-10.diff.  The
second part puts translation of MacOS X keycodes to characters on a
better footing. The first part relaxs Tk's policy of consuming all
events unless it can see they go to windows it didn't create.  This
change gets the little traffic lights working, and should make things
like QuickTimeTcl easier to implement.
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
d28 11
d42 1
@


1.5.2.1
log
@* keyArray: Add 0x34 as <Return>.  Add notes.  (Merge from
  trunk 1.6)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5 2003/02/19 19:27:47 wolfsuit Exp $
a27 11
/*
 * Notes on keyArray:
 *
 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
 *
 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
 * applications don't use it like that.
 *
 * All other keycodes are taken from the published ADB keyboard layouts.
 */

a30 1
    {0x34,  XK_Return},
@


1.5.2.2
log
@Backport Mac OS X specific fixes from TOT. See ChangeLog for details.

In tk_getOpenFile filters, handle the case where you have a Macintosh
file type and the files have no filetype.

Fix various formatting nits.
@
text
@d4 1
a4 1
 *      Routines to support keyboard events on the Macintosh.
d12 1
a12 1
 * RCS: @@(#) $Id$
d21 1
a21 21
                                 * function should probably move here. */

/*
 * A couple of simple definitions to make code a bit more self-explaining.
 *
 * For the assignments of Mod1==alt==command and Mod2==meta==option, see also
 * tkMacOSXMouseEvent.c.
 */

#define LATIN1_MAX       255
#define MAC_KEYCODE_MAX  0x7F
#define MAC_KEYCODE_MASK 0x7F
#define ALT_MASK         Mod1Mask
#define OPTION_MASK      Mod2Mask


/*
 * Tables enumerating the special keys defined on Mac keyboards.  These are
 * necessary for correct keysym mappings for all keys where the keysyms are
 * not identical with their ASCII or Latin-1 code points.
 */
d24 2
a25 2
    int keycode;                /* Macintosh keycode. */
    KeySym keysym;              /* X windows keysym. */
a32 2
 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
 *
d34 1
a34 1
 * applications don't use it like that, nor does Apple's X11.
d40 18
a57 22
    {0x24,      XK_Return},
    {0x30,      XK_Tab},
    {0x33,      XK_BackSpace},
    {0x34,      XK_Return},
    {0x35,      XK_Escape},

    {0x47,      XK_Clear},
    {0x4C,      XK_Return},

    {0x72,      XK_Help},
    {0x73,      XK_Home},
    {0x74,      XK_Page_Up},
    {0x75,      XK_Delete},
    {0x77,      XK_End},
    {0x79,      XK_Page_Down},

    {0x7B,      XK_Left},
    {0x7C,      XK_Right},
    {0x7D,      XK_Down},
    {0x7E,      XK_Up},

    {0,         0}
d60 17
a76 17
static KeyInfo virtualkeyArray[] = {
    {122,       XK_F1},
    {120,       XK_F2},
    {99,        XK_F3},
    {118,       XK_F4},
    {96,        XK_F5},
    {97,        XK_F6},
    {98,        XK_F7},
    {100,       XK_F8},
    {101,       XK_F9},
    {109,       XK_F10},
    {103,       XK_F11},
    {111,       XK_F12},
    {105,       XK_F13},
    {107,       XK_F14},
    {113,       XK_F15},
    {0,         0}
d80 3
a82 6
static Tcl_HashTable keycodeTable;      /* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;         /* virtualkeyArray hashed by virtual
                                         * keycode value. */

static int latin1Table[LATIN1_MAX+1];   /* Reverse mapping table for
                                         * controls, ASCII and Latin-1.  */
d87 1
a87 4

static void     InitKeyMaps (void);
static void     InitLatin1Table(Display *display);
static int      XKeysymToMacKeycode(Display *display, KeySym keysym);
d95 1
a95 5
 *      Creates hash tables used by some of the functions in this file.
 *
 *      FIXME: As keycodes are defined to be in the limited range 0-127, it
 *      would be easier and more efficient to use directly initialized plain
 *      arrays and drop this function.
d98 1
a98 1
 *      None.
d101 1
a101 1
 *      Allocates memory & creates some hash tables.
d112 1
a112 1
                
d115 3
a117 3
        hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
d120 4
a123 4
    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
        hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
                &dummy);
        Tcl_SetHashValue(hPtr, kPtr->keysym);
a130 76
 * InitLatin1Table --
 *
 *      Creates a simple table to be used for mapping from keysyms to
 *      keycodes.  Always needs to be called before using latin1Table,
 *      because the keyboard layout may have changed, and than the table must
 *      be re-computed.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Sets the global latin1Table.
 *
 *----------------------------------------------------------------------
 */

static void
InitLatin1Table(
    Display *display)
{
    static Boolean latin1_initialized = false;
    static SInt16 lastKeyLayoutID = -1;

    SInt16 keyScript;
    SInt16 keyLayoutID;

    keyScript = GetScriptManagerVariable(smKeyScript);
    keyLayoutID = GetScriptVariable(keyScript,smScriptKeys);

    if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) {
        int keycode;
        KeySym keysym;
        int state;
        int modifiers;

        latin1_initialized = true;
        lastKeyLayoutID = keyLayoutID;

        memset(latin1Table, 0, sizeof(latin1Table));
        
        /*
         * In the common X11 implementations, a keymap has four columns
         * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift".  We
         * don't use "Mode_switch", but we use "Option" instead.  (This is
         * similar to Apple's X11 implementation, where "Mode_switch" is used
         * as an alias for "Option".)
         *
         * So here we go through all 4 columns of the keymap and find all
         * Latin-1 compatible keycodes.  We go through the columns
         * back-to-front from the more exotic columns to the more simple, so
         * that simple keycode-modifier combinations are preferred in the
         * resulting table.
         */

        for (state = 3; state >= 0; state--) {
            modifiers = 0;
            if (state & 1) {
                modifiers |= shiftKey;
            }
            if (state & 2) {
                modifiers |= optionKey;
            }

            for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
                keysym = XKeycodeToKeysym(display,keycode<<16,state);
                if (keysym <= LATIN1_MAX) {
                    latin1Table[keysym] = keycode | modifiers;
                }
            }
        }
    }
}

/*
 *----------------------------------------------------------------------
 *
d133 2
a134 2
 *      Translate from a system-dependent keycode to a system-independent
 *      keysym.
d137 1
a137 1
 *      Returns the translated keysym, or NoSymbol on failure.
d140 1
a140 1
 *      None.
d149 1
a149 1
    int index)
d152 2
a156 2
    (void) display; /*unused*/

d158 14
a171 1
        InitKeyMaps();
d175 4
a178 4
     * When determining what keysym to produce we first check to see if the
     * key is a function key.  We then check to see if the character is
     * another non-printing key.  Finally, we return the key syms for all
     * ASCII and Latin-1 chars.
d180 3
a182 6

    newKeycode = keycode >> 16;

    if ((keycode & 0xFFFF) == 0x10) {
        hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
        if (hPtr != NULL) {
d184 1
a184 1
        }
d186 1
a186 1
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode);
d188 1
a188 1
        return (KeySym) Tcl_GetHashValue(hPtr);
d192 2
a193 1
     * Add in the Mac modifier flags for shift and option.
d195 3
a197 6

    if (index & 1) {
        newKeycode |= shiftKey;
    }
    if (index & 2) {
        newKeycode |= optionKey;
d202 2
a203 2
        &newChar, 1, kEventRawKeyDown,
        newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d209 2
a210 3

    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
        return newChar;
d221 1
a221 1
 *      Retrieve the string equivalent for the given keyboard event.
d224 1
a224 1
 *      Returns the UTF string.
d227 1
a227 1
 *      None.
d234 5
a238 5
    TkWindow *winPtr,           /* Window where event occurred: Needed to get
                                 * input context. */
    XEvent *eventPtr,           /* X keyboard event. */
    Tcl_DString *dsPtr)         /* Uninitialized or empty string to hold
                                 * result. */
d250 1
a250 1
 *      Fetch the current keycodes used as modifiers.
d253 1
a253 1
 *      Returns a new modifier map.
d256 1
a256 1
 *      Allocates a new modifier map data structure.
a266 7
    (void) display; /*unused*/

    /*
     * MacOSX doesn't use the key codes for the modifiers for anything, and
     * we don't generate them either.  So there is no modifier map.
     */

d278 2
a279 1
 *      Deallocate a modifier map that was created by XGetModifierMapping.
d282 1
a282 1
 *      None.
d285 1
a285 1
 *      Frees the datastructure referenced by modmap.
d295 1
a295 1
        ckfree((char *) modmap->modifiermap);
d305 4
a308 4
 *      These X window functions map keysyms to strings & strings to keysyms.
 *      However, Tk already does this for the most common keysyms.
 *      Therefore, these functions only need to support keysyms that will be
 *      specific to the Macintosh.  Currently, there are none.
d311 1
a311 1
 *      None.
d314 1
a314 1
 *      None.
d328 1
a328 1
    const char* string)
a335 64
 * XKeysymToMacKeycode --
 *
 *      An internal function like XKeysymToKeycode but only generating the
 *      Mac specific keycode plus the modifiers Shift and Option.
 *
 * Results:
 *      A Mac keycode with the actual keycode in the low byte and Mac-style
 *      modifier bits in the high byte.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

static int
XKeysymToMacKeycode(
    Display *display,
    KeySym keysym)
{
    if (keysym <= LATIN1_MAX) {

        /*
         * Handle keysyms in the Latin-1 range where keysym and Unicode
         * character code point are the same.
         */

        InitLatin1Table(display);
        return latin1Table[keysym];

    } else {

        /*
         * Handle special keys from our exception tables.  Don't mind if this
         * is slow, neither the test suite nor [event generate] need to be
         * optimized (we hope).
         */

        KeyInfo *kPtr;
                
        for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }
        for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
            if (kPtr->keysym == keysym) {
                return kPtr->keycode;
            }
        }

        /*
         * For other keysyms (not Latin-1 and not special keys), we'd need a
         * generic keysym-to-unicode table.  We don't have that, so we give
         * up here.
         */

        return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
d338 5
a342 3
 *      The function XKeysymToKeycode takes an X11 keysym and converts it
 *      into a Mac keycode.  It is in the stubs table for compatibility but
 *      not used anywhere in the core.
d345 1
a345 3
 *      A 32 bit keycode with the the mac keycode (without modifiers) in the
 *      higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *      lower 8 bits of the keycode.
d348 1
a348 1
 *      None.
d358 2
a359 2
    int macKeycode = XKeysymToMacKeycode(display, keysym);
    KeyCode result;
a360 19
    /*
     * See also TkpSetKeycodeAndState.  The 0x0010 magic is used in
     * XKeycodeToKeysym.  For special keys like XK_Return the lower 8 bits of
     * the keysym are usually a related ASCII control code.
     */

    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
        result = 0x0010;
    } else {
        result = 0x00FF & keysym;
    }
    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;

    return result;
}

/*
NB: Keep this commented code for a moment for reference.

d378 1
a378 1
        keycode = keysym + (virtualKeyCode <<16);
d382 1
a382 1
*/
d385 5
a389 19
 *----------------------------------------------------------------------
 *
 * TkpSetKeycodeAndState --
 *
 *      The function TkpSetKeycodeAndState takes a keysym and fills in the
 *      appropriate members of an XEvent.  It is similar to XKeysymToKeycode,
 *      but it also sets the modifier mask in the XEvent.  It is used by
 *      [event generate] and it is in the stubs table.
 *
 * Results:
 *      Fills an XEvent, sets the member xkey.keycode with a keycode
 *      formatted the same as XKeysymToKeycode and the member xkey.state with
 *      the modifiers implied by the keysym.  Also fills in xkey.trans_chars,
 *      so that the actual characters can be retrieved later.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
d393 13
a405 7
TkpSetKeycodeAndState(
    Tk_Window tkwin,
    KeySym keysym,
    XEvent *eventPtr)
{
    if (keysym == NoSymbol) {
        eventPtr->xkey.keycode = 0;
d407 17
a423 28
        Display *display = Tk_Display(tkwin);
        int macKeycode = XKeysymToMacKeycode(display, keysym);

        /*
         * See also XKeysymToKeycode.
         */

        if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
            eventPtr->xkey.keycode = 0x0010;
        } else {
            eventPtr->xkey.keycode = 0x00FF & keysym;
        }
        eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

        if (shiftKey & macKeycode) {
            eventPtr->xkey.state |= ShiftMask;
        }
        if (optionKey & macKeycode) {
            eventPtr->xkey.state |= OPTION_MASK;
        }

        if (keysym <= LATIN1_MAX) {
            int done;
            done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
            eventPtr->xkey.trans_chars[done] = 0;
        } else {
            eventPtr->xkey.trans_chars[0] = 0;
        }
d425 1
d433 2
a434 2
 *      Given an X KeyPress or KeyRelease event, map the keycode in the event
 *      into a keysym.
d437 3
a439 2
 *      The return value is the keysym corresponding to eventPtr, or NoSymbol
 *      if no matching keysym could be found.
d442 2
a443 2
 *      In the first call for a given display, keycode-to-keysym maps get
 *      loaded.
d449 4
a452 3
TkpGetKeySym(
    TkDisplay *dispPtr,         /* Display in which to map keycode. */
    XEvent *eventPtr)           /* Description of X event. */
d458 1
a458 1
     * Refresh the mapping information if it's stale.
d462 1
a462 34
        TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Handle pure modifier keys specially.  We use -1 as a signal for
     * this.
     */

    if (eventPtr->xany.send_event == -1) {
        int modifier = eventPtr->xkey.keycode;
        if (modifier == cmdKey) {
            return XK_Alt_L;
        } else if (modifier == shiftKey) {
            return XK_Shift_L;
        } else if (modifier == alphaLock) {
            return XK_Caps_Lock;
        } else if (modifier == optionKey) {
            return XK_Meta_L;
        } else if (modifier == controlKey) {
            return XK_Control_L;
        } else if (modifier == rightShiftKey) {
            return XK_Shift_R;
        } else if (modifier == rightOptionKey) {
            return XK_Meta_R;
        } else if (modifier == rightControlKey) {
            return XK_Control_R;
        } else {

            /*
             * If we get here, we probably need to implement something new.
             */

            return NoSymbol;
        } 
d466 3
a468 4
     * Figure out which of the four slots in the keymap vector to use for
     * this key.  Refer to Xlib documentation for more info on how this
     * computation works.  (Note: We use "Option" in keymap columns 2 and 3
     * where other implementations have "Mode_switch".)
d472 2
a473 9

    /*
     * We want Option key combinations to use their base chars as keysyms, so
     * we ignore the option modifier here.
     */

#if 0
    if (eventPtr->xkey.state & OPTION_MASK) {
        index |= 2;
a474 2
#endif

d476 27
a502 3
            || (/* (dispPtr->lockUsage != LU_IGNORE)
                   && */ (eventPtr->xkey.state & LockMask))) {
        index |= 1;
a503 5

    /*
     * First try of the actual translation.
     */

d507 4
a510 3
     * Special handling: If the key was shifted because of Lock, but lock is
     * only caps lock, not shift lock, and the shifted keysym isn't
     * upper-case alphabetic, then switch back to the unshifted keysym.
d514 8
a521 14
            /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {

        /*
         * FIXME: Keysyms are only identical to Unicode for ASCII and
         * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
         * that range.  This may be a serious problem here.
         */

        if ((sym == NoSymbol) || (sym > LATIN1_MAX)
                || !Tcl_UniCharIsUpper(sym)) {
            index &= ~1;
            sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                    index);
        }
d525 2
a526 2
     * Another bit of special handling: If this is a shifted key and there is
     * no keysym defined, then use the keysym for the unshifted key.
d530 2
a531 2
        sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
                index & ~1);
d541 4
a544 3
 *      This procedure is invoked to scan keymap information to recompute
 *      stuff that's important for binding, such as the modifier key (if any)
 *      that corresponds to the "Mode_switch" keysym.
d547 1
a547 1
 *      None.
d550 1
a550 1
 *      Keymap-related information in dispPtr is updated.
d556 10
a565 4
TkpInitKeymapInfo(
    TkDisplay *dispPtr)         /* Display for which to recompute keymap
                                 * information. */
{
d567 1
d570 26
a595 3
     * Behaviours that are variable on X11 are defined constant on MacOSX.
     * lockUsage is only used above in TkpGetKeySym(), nowhere else
     * currently.  There is no offical "Mode_switch" key.
a597 1
    dispPtr->lockUsage = LU_CAPS;
d599 19
a617 2
    dispPtr->altModMask = ALT_MASK;
    dispPtr->metaModMask = OPTION_MASK;
d620 1
a620 5
     * MacOSX doesn't use the keycodes for the modifiers for anything, and we
     * don't generate them either (the keycodes actually given in the
     * simulated modifier events are bogus).  So there is no modifier map.
     * If we ever want to simulate real modifier keycodes, the list will be
     * constant in the Carbon implementation.
d624 1
a624 1
        ckfree((char *) dispPtr->modKeyCodes);
d627 37
a663 1
    dispPtr->modKeyCodes = NULL;
@


1.5.2.3
log
@* (TkpInitKeymapInfo): Don't make <Alt> and <Meta> synonyms
  for <Command> and <Option> for now. (Copied from 1.17)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.2 2004/02/16 00:42:34 wolfsuit Exp $
a807 10

#if 0
    /*
     * With this, <Alt> and <Meta> become synonyms for <Command> and <Option>
     * in bindings like they are (and always have been) in the keysyms that
     * are reported by KeyPress events.  But the init scripts like text.tcl
     * have some disabling bindings for <Meta>, so we don't want this without
     * some changes in those scripts.  See also bug #700311.
     */

a809 4
#else
    dispPtr->altModMask = 0;
    dispPtr->metaModMask = 0;
#endif
@


1.5.2.4
log
@	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXNotify.c: introduction of new tcl notifier based on
	CFRunLoop allows replacement of the custom TkAqua notifier by a
	standard tcl event source. Removes requirement of threaded tcl core
	for TkAqua, allows to stub-link TkAqua against Tcl by removing use of
	the unstubbed TclInitNotifier & TclFinalizeNotifier. [Tcl Patch 1202052]

	* macosx/Wish.pbproj/project.pbxproj: stub-link TkAqua: build with
	USE_TCL_STUBS and link against libtclstub instead of Tcl.framework,
	unexport libtclstub symbols from Tk to avoid duplicate symbol warnings
	when linking with both Tcl and Tk, fixes for gcc4.0 warnings.

	* macosx/tkMacOSXBitmap.c:
	* macosx/tkMacOSXButton.c:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c: fixed gcc 4.0 warnings.

	* unix/tcl.m4: sync with tcl
	* unix/configure: autoconf-2.13
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.3 2004/02/25 13:29:41 cc_benny Exp $
a32 1
#undef ALT_MASK
@


1.5.2.5
log
@	* macosx/tkMacOSX.h:             Cleaned up & rationalized order of
	* macosx/tkMacOSXBitmap.c:       #includes of tk and carbon headers;
	* macosx/tkMacOSXButton.c:       sync whitespace, comments & minor
	* macosx/tkMacOSXCarbonEvents.c: changes with HEAD.
	* macosx/tkMacOSXClipboard.c:
	* macosx/tkMacOSXColor.c:
	* macosx/tkMacOSXConfig.c:
	* macosx/tkMacOSXCursor.c:
	* macosx/tkMacOSXDialog.c:
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXEmbed.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXEvent.c:
	* macosx/tkMacOSXEvent.h:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXFont.h (new file):
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXInt.h:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXNotify.c:
	* macosx/tkMacOSXRegion.c:
	* macosx/tkMacOSXScale.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXTest.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXWm.h:
	* macosx/tkMacOSXXStubs.c:
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.4 2005/05/14 20:53:31 das Exp $
d15 4
@


1.5.2.6
log
@	* generic/tkBind.c (TkBindInit): for REDO_KEYSYM_LOOKUP, change
	keysym-to-string mapping hash to use first name in ks_names.h instead of
	last (if there are multiple possibilities), e.g. "F11" instead of "L1".

	* macosx/tkMacOSXKeyboard.c (TkpGetKeySym): correct keysyms for pure
	modifier key presses [Bugs 700311, 1525905]; correct keysym for Enter
	key; add keysyms for new NumLock and Fn modifiers (added 2005-08-09).
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.5 2006/03/28 02:44:13 das Exp $
d22 1
a22 1
 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
d29 2
a30 1
#define COMMAND_MASK     Mod1Mask
d66 1
a66 1
    {0x4C,      XK_KP_Enter},
d680 1
a680 1
            return XK_Meta_L;
d686 1
a686 1
            return XK_Alt_L;
a688 4
        } else if (modifier == kEventKeyModifierNumLockMask) {
            return XK_Num_Lock;
        } else if (modifier == kEventKeyModifierFnMask) {
            return XK_Super_L;
d692 1
a692 1
            return XK_Alt_R;
d815 2
a816 2
    dispPtr->altModMask = OPTION_MASK;
    dispPtr->metaModMask = COMMAND_MASK;
@


1.5.2.7
log
@	* macosx/tkMacOSXCarbonEvents.c: add window event target carbon event
	* macosx/tkMacOSXEvent.c:	 handler for all kEventClassWindow and
	* macosx/tkMacOSXEvent.h:	 kEventClassMouse events; move all
	* macosx/tkMacOSXNotify.c:	 remaining events except for
	* macosx/tkMacOSXWindowEvent.c:	 kEventClassKeyboard from dispatcher to
	application event handler; pass event handler callRef downstream; fix
	debug event tracing; process all tcl event types in carbon event timer;
	delay carbon event timer first fire; add TkMacOSXTrackingLoop() to mark
	enter/exit of event tracking loop during which all tcl events but only
	carbon update events should be processed by the timer (replaces various
	calls to Tcl_SetServiceMode()); rename TkMacOSXReceiveAndProcessEvent()
	to TkMacOSXReceiveAndDispatchEvent(), move it from tkMacOSXEvent.c to
	tkMacOSXCarbonEvents.c and modify it to dequeue only update events
	during a tracking loop; add TkMacOSXRunTclEventLoop() to standardize
	the various ways in use to run the tcl event loop; add handling of
	kEventClassAppearance events (for ScrollBarVariantChanged event).

	* macosx/tkMacOSXDialog.c:	use new TkMacOSXTrackingLoop() around
	* macosx/tkMacOSXEvent.c:	blocking API that puts up modal dialogs
	* macosx/tkMacOSXMenu.c:	or when entering/exiting menu/control
	* macosx/tkMacOSXMouseEvent.c:	tracking, window dragging and other
	* macosx/tkMacOSXScale.c:	mouse tracking loops.
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:

	* macosx/tkMacOSXDialog.c:	use new TkMacOSXRunTclEventLoop()
	* macosx/tkMacOSXScale.c:	instead of Tcl_DoOneEvent(),
	* macosx/tkMacOSXScrlbr.c:	Tcl_ServiceAll(), TclServiceIdle()
	* macosx/tkMacOSXWindowEvent.c:	and Tcl_GlobalEval("update idletasks").

	* macosx/tkMacOSXColor.c: make available as Tk system colors all
	* macosx/tkMacOSXPort.h:  appearance manager brushes, text colors and
	backgrounds with new and legacy names, as well as the fully transparent
	color "systemTransparent"; add TkMacOSXSetColorIn{Port,Context}() to
	directly set an X pixel color value in the current QD port resp. the
	given CG context without requiring passage through rgb representation
	(lossy for most system colors); modernize/remove Classic-era code;
	replace crufty strcmp() elseifs by Tcl_GetIndexFromObjStruct().

	* macosx/tkMacOSXButton.c:	use new TkMacOSXSetColorInPort()
	* macosx/tkMacOSXDraw.c:	instead of setting rgb color directly
	* macosx/tkMacOSXMenubutton.c:	to allow for non-rgb system colors.

	* macosx/tkMacOSXCursor.c: implement "none" cursor as on other
	platforms [Patch 1615427]; add all missing appearance manager cursors.

	* macosx/tkMacOSXDefault.h: set SELECT_FG_COLORs to None to match aqua
	L&F; use standard system color names; use new 'menu' system font;
	correct default scrollbar width.

	* macosx/tkMacOSXDraw.c:	standardize initialization, use and
	* macosx/tkMacOSXInt.h:		emptying of various static temp rgns
	* macosx/tkMacOSXRegion.c:	onto two global RgnHandles; in debug
	* macosx/tkMacOSXSubwindows.c:	builds, verify emptiness of these temp
	* macosx/tkMacOSXWindowEvent.c:	rgns before use.

	* macosx/tkMacOSXDraw.c: add TkMacOSX{Setup,Restore}DrawingContext() to
	* macosx/tkMacOSXInt.h:  abstract common setup & teardown of drawing
	environment (for both CG and QD); save/restore QD theme drawing state;
	handle GC clip region; add TkpClipDrawableToRect() to allow clipped
	drawing into drawable regardless of GC used; use new system color
	"systemWindowHeaderBackground" to setup background in themed toplevels;
	correct implementation of TkMacOSXMakeStippleMap().

	* macosx/tkMacOSXEntry.c: use new TkMacOSXSetupDrawingContext() and
	* macosx/tkMacOSXFont.c:  TkMacOSXRestoreDrawingContext() instead of
	various setup/teardown procs like TkMacOSX{SetUp,Release}CGContext(),
	TkMacOSXQuarz{Start,End}Draw(), TkMacOSXSetUpGraphicsPort() etc.

	* macosx/tkMacOSXEmbed.c: add CG context and drawable clip rgn fields
	* macosx/tkMacOSXInt.h:   to MacDrawable struct.
	* macosx/tkMacOSXSubwindows.c:

	* macosx/tkMacOSXDialog.c: make -parent option of tk_getOpenFile et al.
	use the sheet version of NavServices dialogs; ensure native parent win
	exists before using StandardSheet API for tk_messageBox [Bug 1677611];
	force sheets to behave like app-modal dialogs via WindowModality() API;
	use more modern ColorPicker API.

	* macosx/tkAboutDlg.r: use themed movable modal dialog, fix (c) year.

	* macosx/tkMacOSXEntry.c:  take xOff/yOff of MacDrawable into account
	when computing locations/bounds to ensure correct posititioning when
	not drawing into intermediate pixmap.

	* macosx/tkMacOSXFont.c: use appearance manager API to map system font
	* macosx/tkMacOSXFont.h: names to TkFonts; add "menu" system font for
	menu item text drawing from MDEF; disable broken QD stippling.

	* macosx/tkMacOSXMenu.c:		large-scale rewrite of custom
	* macosx/tkMacOSXMenu.r (removed):	MDEF and related code that
	* unix/Makefile.in:			restores many longtime-MIA
	features to working order (e.g. images, custom colors & fonts in menus
	etc); implement compound menu items; use Appearance Mgr and ThemeText
	APIs to mimic native MDEF as closely as possible when default "menu"
	system font is used; remove now obsolete SICN drawing code and
	resources.

	* macosx/tkMacOSXCarbonEvents.c: handle additional menu carbon events
	* macosx/tkMacOSXEvent.c:	 in order to support <<MenuSelect>> in
	* macosx/tkMacOSXMenu.c:	 the menubar and in menus that are not
	* macosx/tkMacOSXMenus.c:	 using the custom MDEF [Bug 1620826];
	fix early and missing clearing of current Tk active menu entry; fix
	extraneous sending of <<MenuSelect>> during active menu entry clearing.

	* macosx/tkMacOSXMouseEvent.c: add support for async window dragging by
	the window server; set the corresponding window attribute by default.

	* macosx/tkMacOSXMouseEvent.c: rationalized handling order of
	non-mousedown events; add TkMacOSXModifierState() to retrieve the
	current key modifiers in carbon format.

	* macosx/tkMacOSXScrlbr.c: use appearance manager API to retrieve
	scrollbar component metrics; add awareness of multiple possibilites for
	scrollbar arrow position in aqua and handle user changes to arrow
	position pref; handle difference in metrics of small & large scrollbar
	variants; handle aqua "jump to here" scrollbar behaviour; correct
	computation of scroll view size and position; enforce min scrollbar
	height to avoid scrollbar component overlap; erase scrollbar area
	outside of standard width; remove broken auto-adjust code; account for
	window class when leaving space for grow box; remove code to manually
	draw grow box; use modern API for thumb scroll proc; replace
	HiliteControl() by modern API; replace control mgr constants with
	appearance mgr equivalents.

	* macosx/tkMacOSXSubwindows.c: use SetWindowBounds() API instead of
	SizeWindow(); invalidate clip regions after X{Map,Unmap}Window as fix
	for [Bug 940117] made them dependent on mapping state; remove unneeded
	calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port;
	use native-endian pixmap on intel; remove obsolete pixmap pix locking.

	* macosx/tkMacOSXWindowEvent.c: handle only the first of a batch of
	kEventAppAvailableWindowBoundsChanged events sent per transaction;
	handle kEventWindowBoundsChanged event to support live window resizing
	and centralized sending of location/size changed ConfigureNotify
	events; ensure HIGrowBox is redrawn after bounds change; constrain
	window after dragging to ensure titlebar is not inacessible
	offscreen or under dock/menubar; handle kEventWindowGetRegion and
	kEventWindowDrawContent for transparent windows to mark resp. paint
	content region as transparent; handle kEventWindowConstrain for
	fullscreen windows to ensure bounds match new screen size; enter/exit
	fullscreen UIMode upon activation/deactivation of fullscreen window.

	* macosx/tkMacOSXWm.c: use live-resize and async-drag carbon window
	* macosx/tkMacOSXWm.h: attributes for toplevels by default; implement
	new [wm attributes] -topmost, -transparent and -fullscreen; refactor
	WmAttributesCmd() parallelling the tkUnixWm.c implementation, use thus
	factored proc to set proxy icon from [wm iconbitmap]; dynamically
	determine default values for toplevel min and max sizes (similar to
	tkWinWm.c impl): min sizes depend on window class & attributes to
	ensure visibility of all titlebar widgets and grow box, max sizes
	depend on maximal window bounds for all active displays; factor out
	code that puts into effect changes to master or override_redirect; use
	RepositionWindow() API to determine staggered initial window bounds;
	correct resize limit calculations, handle gridding and use modern
	resize API in TkMacOSXGrowToplevel(); remove sending of ConfigureNotify
	after resize or zoom (now handled by BoundsChanged handler); correct
	composite carbon window attribute handling, remove currently unusable
	attributes and add new attributes in [tk::unsupported::MacWindowStyle];
	ensure validity of window class and attributes before use; apply
	changes to window class when handling carbon window attribute changes
	(if HIWindowChangeClass() API available); add debug build warning
	message when deprecated window style is used instead of window class;
	use transparent HIGrowBox for resizable windows; avoid unnecessary
	calls to window structure width API; use tcl time API in TkpGetMS();
	add TkMacOSXEnterExitFullscreen() to enter/exit UIMode with dock and
	menubar hidden; restrict wmTracing output to debug builds; remove
	unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD
	port; workaround GetWindowStructureWidths() Carbon bug (bogus results
	for never-mapped floating windows).

	* macosx/tkMacOSXXStubs.c (TkMacOSXDisplayChanged): add maximal window
	bounds field to Screen record (in ext_data), computed as the union of
	available window positioning bounds of all graphics devices (displays).

	* macosx/tkMacOSXBitmap.c: fix macRoman encoding leak.
	* macosx/tkMacOSXCursor.c:

	* macosx/tkMacOSXDebug.c (TkMacOSXCarbonEventToAscii): use static
	* macosx/tkMacOSXDebug.h: buffer to simplify callers; const fixes.

	* macosx/tkMacOSXBitmap.c: use more efficient QDSwapPort() instead of
	* macosx/tkMacOSXButton.c: GetPort()/SetPort()/GetGWorld()/SetGWorld().
	* macosx/tkMacOSXDraw.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXScale.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXColor.c: use kHIToolboxVersionNumber for runtime OS
	* macosx/tkMacOSXEntry.c: version check rather than Gestalt() etc.
	* macosx/tkMacOSXInt.h:
	* macosx/tkMacOSXWm.c:

	* macosx/tkMacOSXDraw.c: remove obsolete and now incorrect
	* macosx/tkMacOSXInt.h:  tkMenuCascadeRgn clipping code.
	* macosx/tkMacOSXMenu.c:

	* macosx/tkMacOSXHLEvents.c: replace Tcl_GlobalEval() resp. Tcl_Eval()
	* macosx/tkMacOSXScrlbr.c:   by Tcl_EvalEx().
	* macosx/tkMacOSXInit.c:

	* macosx/tkMacOSXInit.c (TkpInit): reorder initialization steps.

	* macosx/tkMacOSXKeyEvent.c: remove pre-10.2 support.

	* macosx/tkMacOSXMenus.c: remove now useless call to
	TkMacOSXHandleTearoffMenu(); use \x.. quoting for non-latin1 macroman
	literar chars to allow file to be edited as utf-8.

	* macosx/tkMacOSXScale.c: replace TrackControl() by modern
	* macosx/tkMacOSXScrlbr.c: HandleControlClick() API (using new
	TkMacOSXModifierState()).

	* macosx/tkMacOSXInt.h:		move all constant #defines needed to
	* macosx/tkMacOSXColor.c:	support building on older OS X releases
	* macosx/tkMacOSXEvent.h:	to a central location in tkMacOSXInt.h.
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXWm.c:

	* macosx/tkMacOSXInt.h:		 add ChkErr() macro to factor out
	* macosx/tkMacOSXButton.c:	 Carbon OSStatus return value checking
	* macosx/tkMacOSXCarbonEvents.c: and TkMacOSXDbgMsg() macro to factour
	* macosx/tkMacOSXClipboard.c:	 out debug message output; use these
	* macosx/tkMacOSXColor.c:	 macros to replace #ifdef TK_MAC_DEBUG
	* macosx/tkMacOSXCursor.c:	 blocks & direct printing to stderr,
	* macosx/tkMacOSXDebug.c:	 and to do additional OSStatus return
	* macosx/tkMacOSXDialog.c:	 checking, and to standardize OSStatus
	* macosx/tkMacOSXDraw.c:	 usage.
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXEvent.c:
	* macosx/tkMacOSXFont.c:
	* macosx/tkMacOSXHLEvents.c:
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXMenu.c:
	* macosx/tkMacOSXMenubutton.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXMouseEvent.c:
	* macosx/tkMacOSXScrlbr.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXSend.c:	remove duplicate/unused declarations.
	* macosx/tkMacOSXXStubs.c:

	* macosx/tkMacOSXDebug.c:	const fixes.
	* macosx/tkMacOSXInit.c:
	* macosx/tkMacOSXTest.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:

	* macosx/Wish-Info.plist.in: add tcl document extensions/mime types and
	LSMinimumSystemVersion, LSRequiresCarbon & NSAppleScriptEnabled keys.

	* macosx/tkMacOSXAETE.r:	fix whitespace.
	* macosx/tkMacOSXConfig.c:
	* macosx/tkMacOSXCursors.r:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXXCursors.r:
	* macosx/README:

	* macosx/Makefile:		fix/add copyright and license refs.
	* macosx/Tk-Info.plist.in:
	* macosx/Wish-Info.plist.in:
	* macosx/tkMacOSX.h:
@
text
@d1 1
a1 1
/*
d4 1
a4 1
 *	Routines to support keyboard events on the Macintosh.
a7 1
 * Copyright (c) 2005-2007 Daniel A. Steffen <das@@users.sourceforge.net>
d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.6 2006/07/21 06:26:54 das Exp $
d16 2
a17 2
#include "tkMacOSXEvent.h"	/* TkMacOSXKeycodeToUnicode() FIXME: That
				 * function should probably move here. */
d26 2
a27 2
#define LATIN1_MAX	 255
#define MAC_KEYCODE_MAX	 0x7F
d29 2
a30 2
#define COMMAND_MASK	 Mod1Mask
#define OPTION_MASK	 Mod2Mask
d34 1
a34 1
 * Tables enumerating the special keys defined on Mac keyboards. These are
d40 2
a41 2
    int keycode;		/* Macintosh keycode. */
    KeySym keysym;		/* X windows keysym. */
d58 20
a77 20
    {0x24,	XK_Return},
    {0x30,	XK_Tab},
    {0x33,	XK_BackSpace},
    {0x34,	XK_Return},
    {0x35,	XK_Escape},

    {0x47,	XK_Clear},
    {0x4C,	XK_KP_Enter},

    {0x72,	XK_Help},
    {0x73,	XK_Home},
    {0x74,	XK_Page_Up},
    {0x75,	XK_Delete},
    {0x77,	XK_End},
    {0x79,	XK_Page_Down},

    {0x7B,	XK_Left},
    {0x7C,	XK_Right},
    {0x7D,	XK_Down},
    {0x7E,	XK_Up},
d79 1
a79 1
    {0,		0}
d83 16
a98 16
    {122,	XK_F1},
    {120,	XK_F2},
    {99,	XK_F3},
    {118,	XK_F4},
    {96,	XK_F5},
    {97,	XK_F6},
    {98,	XK_F7},
    {100,	XK_F8},
    {101,	XK_F9},
    {109,	XK_F10},
    {103,	XK_F11},
    {111,	XK_F12},
    {105,	XK_F13},
    {107,	XK_F14},
    {113,	XK_F15},
    {0,		0}
d102 3
a104 3
static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;		/* virtualkeyArray hashed by virtual
					 * keycode value. */
d106 2
a107 2
static int latin1Table[LATIN1_MAX+1];	/* Reverse mapping table for
					 * controls, ASCII and Latin-1. */
d113 3
a115 3
static void	InitKeyMaps (void);
static void	InitLatin1Table(Display *display);
static int	XKeysymToMacKeycode(Display *display, KeySym keysym);
d123 1
a123 1
 *	Creates hash tables used by some of the functions in this file.
d125 3
a127 3
 *	FIXME: As keycodes are defined to be in the limited range 0-127, it
 *	would be easier and more efficient to use directly initialized plain
 *	arrays and drop this function.
d130 1
a130 1
 *	None.
d133 1
a133 1
 *	Allocates memory & creates some hash tables.
d139 1
a139 1
InitKeyMaps(void)
d144 1
a144 1

d147 3
a149 3
	hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
d153 3
a155 3
	hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
d165 4
a168 4
 *	Creates a simple table to be used for mapping from keysyms to
 *	keycodes. Always needs to be called before using latin1Table,
 *	because the keyboard layout may have changed, and than the table must
 *	be re-computed.
d171 1
a171 1
 *	None.
d174 1
a174 1
 *	Sets the global latin1Table.
d193 40
a232 40
	int keycode;
	KeySym keysym;
	int state;
	int modifiers;

	latin1_initialized = true;
	lastKeyLayoutID = keyLayoutID;

	memset(latin1Table, 0, sizeof(latin1Table));

	/*
	 * In the common X11 implementations, a keymap has four columns
	 * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We
	 * don't use "Mode_switch", but we use "Option" instead. (This is
	 * similar to Apple's X11 implementation, where "Mode_switch" is used
	 * as an alias for "Option".)
	 *
	 * So here we go through all 4 columns of the keymap and find all
	 * Latin-1 compatible keycodes. We go through the columns
	 * back-to-front from the more exotic columns to the more simple, so
	 * that simple keycode-modifier combinations are preferred in the
	 * resulting table.
	 */

	for (state = 3; state >= 0; state--) {
	    modifiers = 0;
	    if (state & 1) {
		modifiers |= shiftKey;
	    }
	    if (state & 2) {
		modifiers |= optionKey;
	    }

	    for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
		keysym = XKeycodeToKeysym(display,keycode<<16,state);
		if (keysym <= LATIN1_MAX) {
		    latin1Table[keysym] = keycode | modifiers;
		}
	    }
	}
d241 2
a242 2
 *	Translate from a system-dependent keycode to a system-independent
 *	keysym.
d245 1
a245 1
 *	Returns the translated keysym, or NoSymbol on failure.
d248 1
a248 1
 *	None.
d253 1
a253 1
KeySym
d266 1
a266 1
	InitKeyMaps();
d271 2
a272 2
     * key is a function key. We then check to see if the character is
     * another non-printing key. Finally, we return the key syms for all
d279 4
a282 4
	hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
	if (hPtr != NULL) {
	    return (KeySym) Tcl_GetHashValue(hPtr);
	}
d286 1
a286 1
	return (KeySym) Tcl_GetHashValue(hPtr);
d289 1
a289 1
    /*
d294 1
a294 1
	newKeycode |= shiftKey;
d297 1
a297 1
	newKeycode |= optionKey;
d302 2
a303 2
	&newChar, 1, kEventRawKeyDown,
	newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
d306 1
a306 1
     * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up
d311 1
a311 1
	return newChar;
d314 1
a314 1
    return NoSymbol;
d322 1
a322 1
 *	Retrieve the string equivalent for the given keyboard event.
d325 1
a325 1
 *	Returns the UTF string.
d328 1
a328 1
 *	None.
d335 5
a339 5
    TkWindow *winPtr,		/* Window where event occurred: Needed to get
				 * input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
d351 1
a351 1
 *	Fetch the current keycodes used as modifiers.
d354 1
a354 1
 *	Returns a new modifier map.
d357 1
a357 1
 *	Allocates a new modifier map data structure.
d362 1
a362 1
XModifierKeymap *
d365 1
a365 1
{
d372 1
a372 1
     * we don't generate them either. So there is no modifier map.
d386 1
a386 1
 *	Deallocate a modifier map that was created by XGetModifierMapping.
d389 1
a389 1
 *	None.
d392 1
a392 1
 *	Frees the datastructure referenced by modmap.
d397 1
a397 1
void
d402 1
a402 1
	ckfree((char *) modmap->modifiermap);
d412 4
a415 4
 *	These X window functions map keysyms to strings & strings to keysyms.
 *	However, Tk already does this for the most common keysyms.
 *	Therefore, these functions only need to support keysyms that will be
 *	specific to the Macintosh. Currently, there are none.
d418 1
a418 1
 *	None.
d421 1
a421 1
 *	None.
d426 1
a426 1
char *
d430 1
a430 1
    return NULL;
d433 1
a433 1
KeySym
d436 1
a436 1
{
d445 2
a446 2
 *	An internal function like XKeysymToKeycode but only generating the
 *	Mac specific keycode plus the modifiers Shift and Option.
d449 2
a450 2
 *	A Mac keycode with the actual keycode in the low byte and Mac-style
 *	modifier bits in the high byte.
d453 1
a453 1
 *	None.
d465 4
a468 4
	/*
	 * Handle keysyms in the Latin-1 range where keysym and Unicode
	 * character code point are the same.
	 */
d470 2
a471 2
	InitLatin1Table(display);
	return latin1Table[keysym];
d475 24
a498 24
	/*
	 * Handle special keys from our exception tables. Don't mind if this
	 * is slow, neither the test suite nor [event generate] need to be
	 * optimized (we hope).
	 */

	KeyInfo *kPtr;

	for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	    if (kPtr->keysym == keysym) {
		return kPtr->keycode;
	    }
	}
	for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
	    if (kPtr->keysym == keysym) {
		return kPtr->keycode;
	    }
	}

	/*
	 * For other keysyms (not Latin-1 and not special keys), we'd need a
	 * generic keysym-to-unicode table. We don't have that, so we give
	 * up here.
	 */
d500 1
a500 1
	return 0;
d509 3
a511 3
 *	The function XKeysymToKeycode takes an X11 keysym and converts it
 *	into a Mac keycode. It is in the stubs table for compatibility but
 *	not used anywhere in the core.
d514 3
a516 3
 *	A 32 bit keycode with the the mac keycode (without modifiers) in the
 *	higher 16 bits of the keycode and the ASCII or Latin-1 code in the
 *	lower 8 bits of the keycode.
d519 1
a519 1
 *	None.
d531 1
a531 1

d533 2
a534 2
     * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
     * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
d539 1
a539 1
	result = 0x0010;
d541 1
a541 1
	result = 0x00FF & keysym;
d552 17
a568 17
	if (keysym == 'a') {
	    virtualKeyCode = 0x00;
	} else if (keysym == 'b' || keysym == 'B') {
	    virtualKeyCode = 0x0B;
	} else if (keysym == 'c') {
	    virtualKeyCode = 0x08;
	} else if (keysym == 'x' || keysym == 'X') {
	    virtualKeyCode = 0x07;
	} else if (keysym == 'z') {
	    virtualKeyCode = 0x06;
	} else if (keysym == ' ') {
	    virtualKeyCode = 0x31;
	} else if (keysym == XK_Return) {
	    virtualKeyCode = 0x24;
	    keysym = '\r';
	}
	keycode = keysym + (virtualKeyCode <<16);
d579 4
a582 4
 *	The function TkpSetKeycodeAndState takes a keysym and fills in the
 *	appropriate members of an XEvent. It is similar to XKeysymToKeycode,
 *	but it also sets the modifier mask in the XEvent. It is used by
 *	[event generate] and it is in the stubs table.
d585 4
a588 4
 *	Fills an XEvent, sets the member xkey.keycode with a keycode
 *	formatted the same as XKeysymToKeycode and the member xkey.state with
 *	the modifiers implied by the keysym. Also fills in xkey.trans_chars,
 *	so that the actual characters can be retrieved later.
d591 1
a591 1
 *	None.
d603 1
a603 1
	eventPtr->xkey.keycode = 0;
d605 2
a606 2
	Display *display = Tk_Display(tkwin);
	int macKeycode = XKeysymToMacKeycode(display, keysym);
d608 25
a632 25
	/*
	 * See also XKeysymToKeycode.
	 */

	if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
	    eventPtr->xkey.keycode = 0x0010;
	} else {
	    eventPtr->xkey.keycode = 0x00FF & keysym;
	}
	eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;

	if (shiftKey & macKeycode) {
	    eventPtr->xkey.state |= ShiftMask;
	}
	if (optionKey & macKeycode) {
	    eventPtr->xkey.state |= OPTION_MASK;
	}

	if (keysym <= LATIN1_MAX) {
	    int done;
	    done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
	    eventPtr->xkey.trans_chars[done] = 0;
	} else {
	    eventPtr->xkey.trans_chars[0] = 0;
	}
d641 2
a642 2
 *	Given an X KeyPress or KeyRelease event, map the keycode in the event
 *	into a keysym.
d645 2
a646 2
 *	The return value is the keysym corresponding to eventPtr, or NoSymbol
 *	if no matching keysym could be found.
d649 2
a650 2
 *	In the first call for a given display, keycode-to-keysym maps get
 *	loaded.
d657 2
a658 2
    TkDisplay *dispPtr,		/* Display in which to map keycode. */
    XEvent *eventPtr)		/* Description of X event. */
d668 1
a668 1
	TkpInitKeymapInfo(dispPtr);
d672 1
a672 1
     * Handle pure modifier keys specially. We use -1 as a signal for
d677 26
a702 26
	int modifier = eventPtr->xkey.keycode;
	if (modifier == cmdKey) {
	    return XK_Meta_L;
	} else if (modifier == shiftKey) {
	    return XK_Shift_L;
	} else if (modifier == alphaLock) {
	    return XK_Caps_Lock;
	} else if (modifier == optionKey) {
	    return XK_Alt_L;
	} else if (modifier == controlKey) {
	    return XK_Control_L;
	} else if (modifier == kEventKeyModifierNumLockMask) {
	    return XK_Num_Lock;
	} else if (modifier == kEventKeyModifierFnMask) {
	    return XK_Super_L;
	} else if (modifier == rightShiftKey) {
	    return XK_Shift_R;
	} else if (modifier == rightOptionKey) {
	    return XK_Alt_R;
	} else if (modifier == rightControlKey) {
	    return XK_Control_R;
	} else {

	    /*
	     * If we get here, we probably need to implement something new.
	     */
d704 2
a705 2
	    return NoSymbol;
	}
d710 2
a711 2
     * this key. Refer to Xlib documentation for more info on how this
     * computation works. (Note: We use "Option" in keymap columns 2 and 3
d724 1
a724 1
	index |= 2;
d729 3
a731 3
	    || (/* (dispPtr->lockUsage != LU_IGNORE)
		   && */ (eventPtr->xkey.state & LockMask))) {
	index |= 1;
d747 1
a747 1
	    /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {
d749 12
a760 12
	/*
	 * FIXME: Keysyms are only identical to Unicode for ASCII and
	 * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside
	 * that range. This may be a serious problem here.
	 */

	if ((sym == NoSymbol) || (sym > LATIN1_MAX)
		|| !Tcl_UniCharIsUpper(sym)) {
	    index &= ~1;
	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    index);
	}
d769 2
a770 2
	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		index & ~1);
d780 3
a782 3
 *	This procedure is invoked to scan keymap information to recompute
 *	stuff that's important for binding, such as the modifier key (if any)
 *	that corresponds to the "Mode_switch" keysym.
d785 1
a785 1
 *	None.
d788 1
a788 1
 *	Keymap-related information in dispPtr is updated.
d795 2
a796 2
    TkDisplay *dispPtr)		/* Display for which to recompute keymap
				 * information. */
d803 1
a803 1
     * currently. There is no offical "Mode_switch" key.
d813 1
a813 1
     * are reported by KeyPress events. But the init scripts like text.tcl
d815 1
a815 1
     * some changes in those scripts. See also bug #700311.
d828 1
a828 1
     * simulated modifier events are bogus). So there is no modifier map.
d834 1
a834 1
	ckfree((char *) dispPtr->modKeyCodes);
@


1.5.2.8
log
@	* macosx/tkMacOSXMenu.c: add error checking; whitespace cleanup.

	* macosx/tkMacOSXDraw.c:	sync comment formatting with HEAD.
	* macosx/tkMacOSXEmbed.c:
	* macosx/tkMacOSXEntry.c:
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXKeyboard.c:
	* macosx/tkMacOSXMenus.c:
	* macosx/tkMacOSXSend.c:
	* macosx/tkMacOSXSubwindows.c:
	* macosx/tkMacOSXWindowEvent.c:
	* macosx/tkMacOSXWm.c:
	* macosx/tkMacOSXXStubs.c:
@
text
@d13 1
a13 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.7 2007/04/29 02:26:49 das Exp $
d17 2
a18 3
#include "tkMacOSXEvent.h"	/* for TkMacOSXKeycodeToUnicode()
				 * FIXME: That function should probably move
				 * here. */
@


1.4
log
@dead keys first fix for MacOSX
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.3 2002/09/09 23:52:02 hobbs Exp $
d20 2
a70 1
static Ptr KCHRPtr;			/* Pointer to 'KCHR' resource. */
a112 4
    KCHRPtr = (Ptr) GetScriptManagerVariable(smKCHRCache);
    if (!KCHRPtr){
        fprintf(stderr,"GetScriptManagerVariable failed\n");
    }
d143 1
a143 1
    unsigned long dummy, newChar;
d184 1
a184 1
       if (index & 0x01) {
a186 3
    dummy = 0;
    newChar = KeyTranslate(KCHRPtr, (short) newKeycode, &dummy);
    c = newChar & charCodeMask;
d188 11
a198 2
    if (c >= XK_space && c < XK_asciitilde) {
  	return c;
@


1.3
log
@	* library/tk.tcl: use command instead of control on Aqua bindings.
	Force dialogs to appear below fixed native Mac menubar.
	* macosx/tkMacOSXKeyEvent.c:
	* macosx/tkMacOSXKeyboard.c: Keypress/release events for pure
	modifier keys were not being passed to Tk.
	Deadkey presses were inserting null characters into text windows.
	Now they do nothing. (Still not ideal, but better than before!)
	* macosx/tkMacOSXMenu.c: Allow more than 200 menus to exist -
	increased to 2000.
	* macosx/tkMacOSXMouseEvent.c: Bad interactions between floating
	windows and ordinary ones.  Ensure that local<->global coordinate
	transformations are wrt to the correct window.
	* macosx/tkMacOSXWm.c: Better error msg for 'wm attributes'.
	Remove crash in 'wm transient'.
	Add 'noActivates' and 'noUpdates' flags to unsupported command.
	[Patch #606658] (darley)
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.2 2002/08/31 06:12:30 das Exp $
d159 1
a159 1
    virtualKey = (char) (keycode >> 16);    
d169 1
a169 1
     * for all ASCI chars.
d225 1
a225 9
    register Tcl_HashEntry *hPtr;
    char string[3];
    int virtualKey;
    int c, len;

    if (!initialized) {
	InitKeyMaps();
    }

d227 1
a227 26
    
    virtualKey = (char) (eventPtr->xkey.keycode >> 16);    
    c = (eventPtr->xkey.keycode) & 0xffff;
    
    if (c < 256) {
        string[0] = (char) c;
        len = 1;
    } else {
        string[0] = (char) (c >> 8);
        string[1] = (char) c;
        len = 2;
    }    
    /*
     * Just return NULL if the character is a function key or another
     * non-printing key.
     */
    if (c == 0x10 || (eventPtr->xany.send_event == -1)) {
	len = 0;
    } else {
	hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
	if (hPtr != NULL) {
	    len = 0;
	}
    }
    return Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, string, 
				    len, dsPtr);
@


1.2
log
@	*** macosx-8-4-branch merged into the mainline [tcl patch #602770] ***

	* generic/tk.decls:
	* generic/tkInt.decls: added new "aqua" specific entries to the
	stubs tables. Changed all "unix" entries to "x11" to allow us to
	distinguish and build both "aqua" on MacOSX and "x11" on MacOSX.

	* generic/tk.h: added a #ifnded RESOURCE_INCLUDED so that tk.h can
	be passed to the resource compiler.

	* generic/tkCmds.c (Tk_TkObjCmd): added [tk windowingsystem]
	subcommand: returns "x11" when running on X11, "win32" on Windows,
	"classic" on MacOS9 and "aqua" on MacOSX Aqua (i.e. Carbon)

	* generic/tkFont.c (TkFontGetFirstTextLayout): new private function
	returning the first chunk of a Tk_TextLayout, i.e. until the first
	font change on the first line (or the whole first line if there is
	no such font change).

	* generic/tkMain.c: made Tcl_ThreadDataKey static

	* library/demos/puzzle.tcl: fixed button metrics for aqua

	* tests/cursor.test: check for presence of arrow cursor instead of
	heart cursor

	* xlib/xcolors.c: changed xColors static initialization to more
	standard C

	* macosx/Wish.pbproj/jingham.pbxuser (new):
	* macosx/Wish.pbproj/project.pbxproj (new): project for Apple's
	ProjectBuilder IDE.

	* macosx/Makefile (new): simple makefile for building the project
	from the command line via the ProjectBuilder tool 'pbxbuild'.

	* macosx/tkMacOSXAppInit.c (new): macosx specific AppInit looking
	for a AppMain.tcl file in its bundled Resources/Scripts folder. If
	present, argv[1] is set to that file and the Scripts folder is
	added to the auto_path. This allows tk apps to embed scripts within
	their bundle directory structure.

	* macosx/tkMacOSXInit.c (new): macosx adapted version of
	tkUnixInit.c: we initialize & cache the Carbon native encoding
	(e.g. 'macRoman') and try to find the tk script library files
	inside Tk packaged as a framework.

	* macosx/tkMacOSXNotify.c (new): new macosx specific merged
	Carbon/select-based notifier.

	* macosx/tkMacOSXEvent.c (new):
	* macosx/tkMacOSXEvent.h (new):
	* macosx/tkMacOSXKeyEvent.c (new):
	* macosx/tkMacOSXMouseEvent.c (new):
	* macosx/tkMacOSXWindowEvent.c (new): new macosx specific event
	handling functionality.

	* macosx/tkMacOSX.h (new):
	* macosx/tkMacOSXBitmap.c (new):
	* macosx/tkMacOSXButton.c (new):
	* macosx/tkMacOSXClipboard.c (new):
	* macosx/tkMacOSXColor.c (new):
	* macosx/tkMacOSXConfig.c (new):
	* macosx/tkMacOSXCursor.c (new):
	* macosx/tkMacOSXDefault.h (new):
	* macosx/tkMacOSXDialog.c (new):
	* macosx/tkMacOSXDraw.c (new):
	* macosx/tkMacOSXEmbed.c (new):
	* macosx/tkMacOSXFont.c (new):
	* macosx/tkMacOSXHLEvents.c (new):
	* macosx/tkMacOSXInt.h (new):
	* macosx/tkMacOSXKeyboard.c (new):
	* macosx/tkMacOSXMenu.c (new):
	* macosx/tkMacOSXMenubutton.c (new):
	* macosx/tkMacOSXMenus.c (new):
	* macosx/tkMacOSXPort.h (new):
	* macosx/tkMacOSXRegion.c (new):
	* macosx/tkMacOSXScale.c (new):
	* macosx/tkMacOSXScrlbr.c (new):
	* macosx/tkMacOSXSubwindows.c (new):
	* macosx/tkMacOSXTest.c (new):
	* macosx/tkMacOSXUtil.c (new):
	* macosx/tkMacOSXUtil.h (new):
	* macosx/tkMacOSXWm.c (new):
	* macosx/tkMacOSXWm.h (new):
	* macosx/tkMacOSXXStubs.c (new): macosx ports of classic mac Tk
	implementation in tk/mac.

	* macosx/tkMacOSXSend.c (new): only send to local interp
	implemented currently.

	* macosx/tkMacOSXDebug.h (new):
	* macosx/tkMacOSXDebug.c (new): new macosx specific functions for
	debugging MacOS events, regions, etc.

	* macosx/tkAboutDlg.r (new):
	* macosx/tkMacOSXApplication.r (new):
	* macosx/tkMacOSXCursors.r (new):
	* macosx/tkMacOSXLibrary.r (new):
	* macosx/tkMacOSXMenu.r (new):
	* macosx/tkMacOSXResource.r (new):
	* macosx/tkMacOSXXCursors.r (new):
	* macosx/tclets.r (new): sources for Rez resource compiler.

	* macosx/Wish.icns (new): Wish application icon.

	* generic/tk.h:
	* generic/default.h:
	* generic/tkBind.c:
	* generic/tkCmds.c:
	* generic/tkGrab.c:
	* generic/tkPointer.c:
	* generic/tkPort.h:
	* generic/tkSelect.c:
	* generic/tkStubLib.c:
	* generic/tkTest.c:
	* generic/tkText.c:
	* generic/tkWindow.c:
	* unix/tkUnix3d.c:
	* xlib/xgc.c:
	* xlib/X11/X.h:
	* xlib/X11/Xlib.h:
	* xlib/X11/Xutil.h: added #includes and #ifdefs for macosx

	* library/bgerror.tcl:
	* library/button.tcl:
	* library/console.tcl:
	* library/dialog.tcl:
	* library/entry.tcl:
	* library/listbox.tcl:
	* library/menu.tcl:
	* library/msgbox.tcl:
	* library/scrlbar.tcl:
	* library/spinbox.tcl:
	* library/text.tcl:
	* library/tk.tcl:
	* library/demos/menu.tcl:
	* library/demos/menubu.tcl:
	* library/demos/widget: check [tk windowingsystem] instead of
	and/or in addition to $tcl_platform(platform).

	* generic/tkInt.h:
	* mac/tkMacBitmap.c:
	* mac/tkMacWm.c: added missing CONSTification

	* generic/tkIntDecls.h:
	* generic/tkIntPlatDecls.h:
	* generic/tkIntXlibDecls.h:
	* generic/tkPlatDecls.h:
	* generic/tkStubInit.c: regen
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
d151 8
d251 1
a251 1
    if (c == 0x10) {
d497 24
@


1.1
log
@file tkMacOSXKeyboard.c was initially added on branch macosx-8-4-branch.
@
text
@d1 650
@


1.1.2.1
log
@First checkin of support for Tk on Mac OS X.
@
text
@a0 648
/* 
 * tkMacOSXKeyboard.c --
 *
 *	Routines to support keyboard events on the Macintosh.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001, Apple Computer, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @@(#) $Id$
 */

#include "tkInt.h"
#include "X11/Xlib.h"
#include "X11/keysym.h"
#include <Carbon/Carbon.h>

typedef struct {
    short keycode;		/* Macintosh keycode */
    KeySym keysym;		/* X windows Keysym */
} KeyInfo;

static KeyInfo keyArray[] = {
    {0x4C,	XK_Return},
    {0x24,	XK_Return},
    {0x33,	XK_BackSpace},
    {0x75,	XK_Delete},
    {0x30,	XK_Tab},
    {0x74,	XK_Page_Up},
    {0x79,	XK_Page_Down},
    {0x73,	XK_Home},
    {0x77,	XK_End},
    {0x7B,	XK_Left},
    {0x7C,	XK_Right},
    {0x7E,	XK_Up},
    {0x7D,	XK_Down},
    {0x72,	XK_Help},
    {0x35,	XK_Escape},
    {0x47,	XK_Clear},
    {0,		0}
};

static KeyInfo vituralkeyArray[] = {
    {122,	XK_F1},
    {120,	XK_F2},
    {99,	XK_F3},
    {118,	XK_F4},
    {96,	XK_F5},
    {97,	XK_F6},
    {98,	XK_F7},
    {100,	XK_F8},
    {101,	XK_F9},
    {109,	XK_F10},
    {103,	XK_F11},
    {111,	XK_F12},
    {105,	XK_F13},
    {107,	XK_F14},
    {113,	XK_F15},
    {0,		0}
};

static int initialized = 0;
static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
static Tcl_HashTable vkeyTable;		/* vituralkeyArray hashed by virtual
					   keycode value. */
static Ptr KCHRPtr;			/* Pointer to 'KCHR' resource. */

/*
 * Prototypes for static functions used in this file.
 */
static void	InitKeyMaps _ANSI_ARGS_((void));


/*
 *----------------------------------------------------------------------
 *
 * InitKeyMaps --
 *
 *	Creates hash tables used by some of the functions in this file.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocates memory & creates some hash tables.
 *
 *----------------------------------------------------------------------
 */

static void
InitKeyMaps()
{
    Tcl_HashEntry *hPtr;
    KeyInfo *kPtr;
    int dummy;
		
    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
    for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) {
	hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
		&dummy);
	Tcl_SetHashValue(hPtr, kPtr->keysym);
    }
    KCHRPtr = (Ptr) GetScriptManagerVariable(smKCHRCache);
    if (!KCHRPtr){
        fprintf(stderr,"GetScriptManagerVariable failed\n");
    }
    initialized = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeycodeToKeysym --
 *
 *	Translate from a system-dependent keycode to a
 *	system-independent keysym.
 *
 * Results:
 *	Returns the translated keysym, or NoSymbol on failure.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeySym 
XKeycodeToKeysym(
    Display* display,
    KeyCode keycode,
    int	index)
{
    register Tcl_HashEntry *hPtr;
    int c;
    char virtualKey;
    int newKeycode;
    unsigned long dummy, newChar;

    if (!initialized) {
	InitKeyMaps();
    }
    virtualKey = (char) (keycode >> 16);    
    c = (keycode) & 0xffff;
    if (c > 255) {
        return NoSymbol;
    }

    /*
     * When determining what keysym to produce we first check to see if
     * the key is a function key.  We then check to see if the character
     * is another non-printing key.  Finally, we return the key syms
     * for all ASCI chars.
     */
    if (c == 0x10) {
	hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
	if (hPtr != NULL) {
            return (KeySym) Tcl_GetHashValue(hPtr);
	}
    }
    hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
    if (hPtr != NULL) {
 	return (KeySym) Tcl_GetHashValue(hPtr);
    }

    /* 
     * Recompute the character based on the Shift key only.
     * TODO: The index may also specify the NUM_LOCK.
     */
    newKeycode = virtualKey;
       if (index & 0x01) {
	newKeycode += 0x0200;
    }
    dummy = 0;
    newChar = KeyTranslate(KCHRPtr, (short) newKeycode, &dummy);
    c = newChar & charCodeMask;

    if (c >= XK_space && c < XK_asciitilde) {
  	return c;
    }

    return NoSymbol; 
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetString --
 *
 *	Retrieve the string equivalent for the given keyboard event.
 *
 * Results:
 *	Returns the UTF string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
TkpGetString(
    TkWindow *winPtr,		/* Window where event occurred:  needed to
				 * get input context. */
    XEvent *eventPtr,		/* X keyboard event. */
    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
				 * result. */
{
    register Tcl_HashEntry *hPtr;
    char string[3];
    char virtualKey;
    int c, len;

    if (!initialized) {
	InitKeyMaps();
    }

    Tcl_DStringInit(dsPtr);
    
    virtualKey = (char) (eventPtr->xkey.keycode >> 16);    
    c = (eventPtr->xkey.keycode) & 0xffff;
    
    if (c < 256) {
        string[0] = (char) c;
        len = 1;
    } else {
        string[0] = (char) (c >> 8);
        string[1] = (char) c;
        len = 2;
    }    
    /*
     * Just return NULL if the character is a function key or another
     * non-printing key.
     */
    if (c == 0x10) {
	len = 0;
    } else {
	hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
	if (hPtr != NULL) {
	    len = 0;
	}
    }
    return Tcl_ExternalToUtfDString(NULL, string, len, dsPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * XGetModifierMapping --
 *
 *	Fetch the current keycodes used as modifiers.
 *
 * Results:
 *	Returns a new modifier map.
 *
 * Side effects:
 *	Allocates a new modifier map data structure.
 *
 *----------------------------------------------------------------------
 */

XModifierKeymap * 
XGetModifierMapping(
    Display* display)
{ 
    XModifierKeymap * modmap;

    modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
    modmap->max_keypermod = 0;
    modmap->modifiermap = NULL;
    return modmap;
}

/*
 *----------------------------------------------------------------------
 *
 * XFreeModifiermap --
 *
 *	Deallocate a modifier map that was created by
 *	XGetModifierMapping.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees the datastructure referenced by modmap.
 *
 *----------------------------------------------------------------------
 */

void 
XFreeModifiermap(
    XModifierKeymap *modmap)
{
    if (modmap->modifiermap != NULL) {
	ckfree((char *) modmap->modifiermap);
    }
    ckfree((char *) modmap);
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToString, XStringToKeysym --
 *
 *	These X window functions map Keysyms to strings & strings to 
 * 	keysyms.  However, Tk already does this for the most common keysyms.  
 *  	Therefor, these functions only need to support keysyms that will be 
 *  	specific to the Macintosh.  Currently, there are none.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char * 
XKeysymToString(
    KeySym keysym)
{
    return NULL; 
}

KeySym 
XStringToKeysym(
    const char*	string)
{ 
    return NoSymbol;
}

/*
 *----------------------------------------------------------------------
 *
 * XKeysymToKeycode --
 *
 *	The function XKeysymToKeycode is only used by tkTest.c and
 *	currently only implementes the support for keys used in the
 *	Tk test suite.
 *      FIXME - This is no longer true.  This function is now used in
 *      "event generate" so we really should make it work.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

KeyCode
XKeysymToKeycode(
    Display* display,
    KeySym keysym)
{
    KeyCode keycode = 0;
    char virtualKeyCode = 0;
    
    if ((keysym >= XK_space) && (XK_asciitilde)) {
        if (keysym == 'a') {
            virtualKeyCode = 0x00;
        } else if (keysym == 'b' || keysym == 'B') {
            virtualKeyCode = 0x0B;
        } else if (keysym == 'c') {
            virtualKeyCode = 0x08;
        } else if (keysym == 'x' || keysym == 'X') {
            virtualKeyCode = 0x07;
        } else if (keysym == 'z') {
            virtualKeyCode = 0x06;
        } else if (keysym == ' ') {
            virtualKeyCode = 0x31;
        } else if (keysym == XK_Return) {
            virtualKeyCode = 0x24;
            keysym = '\r';
        }
	keycode = keysym + (virtualKeyCode <<16);
    }

    return keycode;
}

/*
 * When mapping from a keysym to a keycode, need
 * information about the modifier state that should be used
 * so that when they call XKeycodeToKeysym taking into
 * account the xkey.state, they will get back the original
 * keysym.
 */

void
TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
    Tk_Window tkwin;
    KeySym keySym;
    XEvent *eventPtr;
{
    Display *display;
    int state;
    KeyCode keycode;
    
    display = Tk_Display(tkwin);
    
    if (keySym == NoSymbol) {
	keycode = 0;
    } else {
	keycode = XKeysymToKeycode(display, keySym);
    }
    if (keycode != 0) {
	for (state = 0; state < 4; state++) {
	    if (XKeycodeToKeysym(display, keycode, state) == keySym) {
		if (state & 1) {
		    eventPtr->xkey.state |= ShiftMask;
		}
		if (state & 2) {
		    TkDisplay *dispPtr;

		    dispPtr = ((TkWindow *) tkwin)->dispPtr; 
		    eventPtr->xkey.state |= dispPtr->modeModMask;
		}
		break;
	    }
	}
    }
    eventPtr->xkey.keycode = keycode;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpGetKeySym --
 *
 *	Given an X KeyPress or KeyRelease event, map the
 *	keycode in the event into a KeySym.
 *
 * Results:
 *	The return value is the KeySym corresponding to
 *	eventPtr, or NoSymbol if no matching Keysym could be
 *	found.
 *
 * Side effects:
 *	In the first call for a given display, keycode-to-
 *	KeySym maps get loaded.
 *
 *----------------------------------------------------------------------
 */

KeySym
TkpGetKeySym(dispPtr, eventPtr)
    TkDisplay *dispPtr;	/* Display in which to
					 * map keycode. */
    XEvent *eventPtr;		/* Description of X event. */
{
    KeySym sym;
    int index;

    /*
     * Refresh the mapping information if it's stale
     */

    if (dispPtr->bindInfoStale) {
	TkpInitKeymapInfo(dispPtr);
    }

    /*
     * Figure out which of the four slots in the keymap vector to
     * use for this key.  Refer to Xlib documentation for more info
     * on how this computation works.
     */

    index = 0;
    if (eventPtr->xkey.state & dispPtr->modeModMask) {
	index = 2;
    }
    if ((eventPtr->xkey.state & ShiftMask)
	    || ((dispPtr->lockUsage != LU_IGNORE)
	    && (eventPtr->xkey.state & LockMask))) {
	index += 1;
    }
    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);

    /*
     * Special handling:  if the key was shifted because of Lock, but
     * lock is only caps lock, not shift lock, and the shifted keysym
     * isn't upper-case alphabetic, then switch back to the unshifted
     * keysym.
     */

    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
	    && (dispPtr->lockUsage == LU_CAPS)) {
	if (!(((sym >= XK_A) && (sym <= XK_Z))
		|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
		|| ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
	    index &= ~1;
	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		    index);
	}
    }

    /*
     * Another bit of special handling:  if this is a shifted key and there
     * is no keysym defined, then use the keysym for the unshifted key.
     */

    if ((index & 1) && (sym == NoSymbol)) {
	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
		index & ~1);
    }
    return sym;
}

/*
 *--------------------------------------------------------------
 *
 * TkpInitKeymapInfo --
 *
 *	This procedure is invoked to scan keymap information
 *	to recompute stuff that's important for binding, such
 *	as the modifier key (if any) that corresponds to "mode
 *	switch".
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Keymap-related information in dispPtr is updated.
 *
 *--------------------------------------------------------------
 */

void
TkpInitKeymapInfo(dispPtr)
    TkDisplay *dispPtr;		/* Display for which to recompute keymap
				 * information. */
{
    XModifierKeymap *modMapPtr;
    KeyCode *codePtr;
    KeySym keysym;
    int count, i, j, max, arraySize;
#define KEYCODE_ARRAY_SIZE 20

    dispPtr->bindInfoStale = 0;
    modMapPtr = XGetModifierMapping(dispPtr->display);

    /*
     * Check the keycodes associated with the Lock modifier.  If
     * any of them is associated with the XK_Shift_Lock modifier,
     * then Lock has to be interpreted as Shift Lock, not Caps Lock.
     */

    dispPtr->lockUsage = LU_IGNORE;
    codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
    for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}
	keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
	if (keysym == XK_Shift_Lock) {
	    dispPtr->lockUsage = LU_SHIFT;
	    break;
	}
	if (keysym == XK_Caps_Lock) {
	    dispPtr->lockUsage = LU_CAPS;
	    break;
	}
    }

    /*
     * Look through the keycodes associated with modifiers to see if
     * the the "mode switch", "meta", or "alt" keysyms are associated
     * with any modifiers.  If so, remember their modifier mask bits.
     */

    dispPtr->modeModMask = 0;
    dispPtr->metaModMask = 0;
    dispPtr->altModMask = 0;
    codePtr = modMapPtr->modifiermap;
    max = 8*modMapPtr->max_keypermod;
    for (i = 0; i < max; i++, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}
	keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
	if (keysym == XK_Mode_switch) {
	    dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
	    dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
	if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
	    dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
	}
    }

    /*
     * Create an array of the keycodes for all modifier keys.
     */

    if (dispPtr->modKeyCodes != NULL) {
	ckfree((char *) dispPtr->modKeyCodes);
    }
    dispPtr->numModKeyCodes = 0;
    arraySize = KEYCODE_ARRAY_SIZE;
    dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
	    (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
    for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
	if (*codePtr == 0) {
	    continue;
	}

	/*
	 * Make sure that the keycode isn't already in the array.
	 */

	for (j = 0; j < dispPtr->numModKeyCodes; j++) {
	    if (dispPtr->modKeyCodes[j] == *codePtr) {
		goto nextModCode;
	    }
	}
	if (dispPtr->numModKeyCodes >= arraySize) {
	    KeyCode *new;

	    /*
	     * Ran out of space in the array;  grow it.
	     */

	    arraySize *= 2;
	    new = (KeyCode *) ckalloc((unsigned)
		    (arraySize * sizeof(KeyCode)));
	    memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
		    (dispPtr->numModKeyCodes * sizeof(KeyCode)));
	    ckfree((char *) dispPtr->modKeyCodes);
	    dispPtr->modKeyCodes = new;
	}
	dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
	dispPtr->numModKeyCodes++;
	nextModCode: continue;
    }
    XFreeModifiermap(modMapPtr);
}
@


1.1.2.2
log
@encodings, events
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.1.2.1 2001/10/15 09:22:00 wolfsuit Exp $
a19 2
extern Tcl_Encoding macRomanEncoding;

d250 1
a250 1
    return Tcl_ExternalToUtfDString(macRomanEncoding, string, len, dsPtr);
@


1.1.2.3
log
@Jim's patch for encodings
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id: tkMacOSXKeyboard.c,v 1.1.2.2 2002/07/18 23:45:18 vincentdarley Exp $
d19 2
a20 1
#include "tkMacOSXInt.h"
d252 1
a252 2
    return Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, string, 
				    len, dsPtr);
@


1.1.2.4
log
@various project cleanups & enhancements
added macosx/Makefile to facilitate building from cli
added [tk windowingsystem] and removed $::tcl_plaform(windowingsystem)
changed all runtime library references to the above
removed duplicate entries in tk.decls & tkInt.decls
CONSTification and other small changes in macosx/ to remove compiler warnings
@
text
@d12 1
a12 1
 * RCS: @@(#) $Id$
d22 1
a22 1
    int keycode;		/* Macintosh keycode */
d144 1
a144 1
    int virtualKey;
d219 1
a219 1
    int virtualKey;
@


