#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- qt-2.3.7/src/kernel/qkeyboard_qws.cpp~kernel-keymap.patch
+++ qt-2.3.7/src/kernel/qkeyboard_qws.cpp
@@ -30,6 +30,34 @@
 **
 **********************************************************************/
 
+/****************************************************************************
+**
+** Keyboard Handling Redesign
+** Copyright 2003, Chris Larson <kergoth@handhelds.org>
+** 
+** TODO: (key: . = in progress, x = completed)
+**
+** [.] Tty driver should load its initial keymap from the kernel,
+**     thereby ensuring keymap consistency between X, console, and qt/e
+**     [x] Read kernel keymappings.
+**     [x] Read kernel keycode -> unicode map.
+**     [x] Use them, along with the existing keyM, to push events up.
+**     [ ] Create a new table, from transformed keycode -> qt keycode, rather
+**         than the existing raw keycode -> qt keycode.
+**     [ ] Adapt handleKey to deal with keys that have no unicode value, such as
+**         keypresses that are mapped to strings in the string table. (e.g. F keys)
+** [ ] Cursor orientation change based on display rotation should not
+**     be bound to Ipaq or 5xxx, but instead as a runtime choice based
+**     on whether or not we're using a Transformed display driver.
+** [ ] Double check that VT handling, particularly with regard to switching,
+**     is handled properly.
+** [ ] Add a generic means of dealing with additional (outside the realm of
+**     ctrl, alt, shift, altgr) modifiers.  Also ensure a means of binding
+**     a keypress/combination to a 'lock' of said additional modifiers.
+**
+**********************************************************************/
+
+
 #include "qwindowsystem_qws.h"
 #include "qwsutils_qws.h"
 #include "qgfx_qws.h"
@@ -46,6 +74,7 @@
 #include <unistd.h>
 #ifdef _OS_LINUX_
 #include <linux/kd.h>
+#include <linux/keyboard.h>
 #endif
 #include <sys/ioctl.h>
 #include <sys/types.h>
@@ -53,6 +82,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <signal.h>
+#include <termios.h>
 
 #ifndef QT_NO_QWS_KEYBOARD
 
@@ -74,11 +104,6 @@
 #include <sys/vt.h>
 #endif
 
-#ifdef QT_QWS_SL5XXX
-#include <asm/sharp_char.h>
-#endif
-
-#if defined(QT_QWS_IPAQ) || defined(QT_QWS_SL5XXX)
 static int dir_keyrot = -1;
 
 static int xform_dirkey(int key)
@@ -102,7 +127,6 @@
     int xf = qt_screen->transformOrientation() + dir_keyrot;
     return (key-Qt::Key_Left+xf)%4+Qt::Key_Left;
 }
-#endif
 
 #define VTSWITCHSIG SIGUSR2
 
@@ -169,11 +193,19 @@
     {	Qt::Key_F35,		0xffff  , 0xffff  , 0xffff  }, // 21 light
     {	Qt::Key_Escape,		0xffff  , 0xffff  , 0xffff  }, // 22
 
+#ifdef QT_QWS_SL6000
     // Direction key code are for *UNROTATED* display.
+    {  Qt::Key_Left,           0xffff  , 0xffff  , 0xffff  }, // 23
+    {  Qt::Key_Up,             0xffff  , 0xffff  , 0xffff  }, // 24
+    {  Qt::Key_Down,           0xffff  , 0xffff  , 0xffff  }, // 25
+    {  Qt::Key_Right,          0xffff  , 0xffff  , 0xffff  }, // 26
+#else
+    // Direction key code are for *UNROTATED* display.
+    {   Qt::Key_Up,             0xffff  , 0xffff  , 0xffff  }, // 23
+    {   Qt::Key_Right,          0xffff  , 0xffff  , 0xffff  }, // 24
+    {   Qt::Key_Left,           0xffff  , 0xffff  , 0xffff  }, // 25
+    {   Qt::Key_Down,           0xffff  , 0xffff  , 0xffff  }, // 26
+#endif
-    {	Qt::Key_Up,		0xffff  , 0xffff  , 0xffff  }, // 23
-    {	Qt::Key_Right,		0xffff  , 0xffff  , 0xffff  }, // 24
-    {	Qt::Key_Left,		0xffff  , 0xffff  , 0xffff  }, // 25
-    {	Qt::Key_Down,		0xffff  , 0xffff  , 0xffff  }, // 26
 
     {	Qt::Key_F33,		0xffff  , 0xffff  , 0xffff  }, // 27 OK
     {	Qt::Key_F12,		0xffff  , 0xffff  , 0xffff  }, // 28 40 home
@@ -246,7 +262,7 @@
     {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 63
     {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 64
     {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 65
-    {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 66
+    {   Qt::Key_F14,    0xffff  , 0xffff  , 0xffff  }, // 66
     {	Qt::Key_Meta,		0xffff  , 0xffff  , 0xffff  }, // 67
     {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 68
     {	Qt::Key_unknown,	0xffff  , 0xffff  , 0xffff  }, // 69
@@ -488,12 +504,18 @@
 public:
     QWSTtyKeyboardHandler(const QString&);
     virtual ~QWSTtyKeyboardHandler();
+    void readKeyboardMap();
+    void readUnicodeMap();
+    void handleKey(unsigned char code);
 
 private slots:
     void readKeyboardData();
 
 private:
     struct termios origTermData;
+    unsigned short acm[E_TABSZ];
+    unsigned char kernel_map[(1<<KG_CAPSSHIFT)][NR_KEYS];
+    int current_map;
 };
 
 class QWSUsbKeyboardHandler : public QWSPC101KeyboardHandler
@@ -633,6 +655,7 @@
     fn = FALSE;
 
     numLock = FALSE;
+#if 0
     sharp_kbdctl_modifstat  st;
     int dev = ::open("/dev/sharp_kbdctl", O_RDWR);
     if( dev >= 0 ) {
@@ -644,6 +667,7 @@
 	::close(dev);
     }
 #endif
+#endif
 #if defined(QT_QWS_IPAQ)
     // iPAQ Action Key has ScanCode 0x60: 0x60|0x80 = 0xe0 == extended mode 1 !
     ipaq_return_pressed = FALSE;
@@ -1023,7 +1047,7 @@
 // Tty keyboard
 //
 
-QWSTtyKeyboardHandler::QWSTtyKeyboardHandler(const QString& device)
+QWSTtyKeyboardHandler::QWSTtyKeyboardHandler(const QString& device) : current_map(0)
 {
     kbdFD=open(device.isEmpty() ? "/dev/tty0" : device.latin1(), O_RDWR | O_NDELAY, 0);
 
@@ -1040,7 +1064,7 @@
 	tcgetattr( kbdFD, &termdata );
 
 #if !defined(_OS_FREEBSD_) && !defined(_OS_SOLARIS_)
-	ioctl(kbdFD, KDSKBMODE, K_RAW);
+	ioctl(kbdFD, KDSKBMODE, K_MEDIUMRAW);
 #endif
 
 	termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
@@ -1053,6 +1077,9 @@
 	cfsetospeed(&termdata, 9600);
 	tcsetattr(kbdFD, TCSANOW, &termdata);
 
+	readUnicodeMap();
+	readKeyboardMap();
+
 	signal(VTSWITCHSIG, vtSwitchHandler);
 
 #if !defined(_OS_FREEBSD_) && !defined(_OS_SOLARIS_)
@@ -1108,9 +1135,122 @@
     unsigned char buf[81];
     int n = read(kbdFD, buf, 80 );
     for ( int loop = 0; loop < n; loop++ )
-	doKey(buf[loop]);
+	handleKey(buf[loop]);
+}
+
+void QWSTtyKeyboardHandler::readUnicodeMap()
+{
+    if (kbdFD < 0)
+        return;
+    if (ioctl(kbdFD,GIO_UNISCRNMAP,acm) != 0)
+        return;
+}
+
+void QWSTtyKeyboardHandler::readKeyboardMap()
+{
+    struct kbentry  kbe;
+    if (kbdFD < 0)
+        return;
+
+    for (int map = 0; map < (1<<KG_CAPSSHIFT); ++map)
+    {
+        unsigned short kval;
+        kbe.kb_table = map;
+
+        for (int key = 0; key < NR_KEYS; ++key)
+        {
+            kbe.kb_index = key;
+
+            if (ioctl(kbdFD, KDGKBENT, &kbe) != 0) continue;
+
+            if ((kbe.kb_value == K_HOLE) || (kbe.kb_value == K_NOSUCHMAP)) continue;
+
+            kval = KVAL(kbe.kb_value);
+            switch (KTYP(kbe.kb_value))
+            {
+                    case KT_LETTER:
+                    case KT_LATIN:
+                    case KT_ASCII:
+                    case KT_PAD:
+                    case KT_SHIFT:
+                        kernel_map[map][key] = kbe.kb_value;
+                        //qWarning("keycode %d, map %d, type %d, val %d, acm %c\n", key, map, KTYP(kbe.kb_value), kval, acm[kval]);
+                        break;
+            }
+        }
+    }
+}
+
+static inline int map_to_modif(int current_map)
+{
+    int modifiers = 0;
+
+    if (current_map & KG_ALT)
+        modifiers |= Qt::ALT;
+    else if (current_map & KG_CTRL)
+        modifiers |= Qt::CTRL;
+    else if (current_map & KG_SHIFT)
+        modifiers |= Qt::SHIFT;
+
+    return modifiers;
 }
 
+void QWSTtyKeyboardHandler::handleKey(unsigned char code)
+{
+    struct kbentry kbe;
+
+    bool release = false;
+    if (code & 0x80)
+    {
+        release = true;
+        code &= 0x7f;
+    }
+
+    unsigned short mCode = KVAL(kernel_map[current_map][code]);
+    unsigned short unicode = acm[mCode];
+
+    const QWSServer::KeyMap *currentKey = 0;
+    int qtKeyCode = Qt::Key_unknown;
+
+    currentKey = &QWSServer::keyMap()[code];
+    if ( currentKey ) qtKeyCode = currentKey->key_code;
+
+    qDebug("code %d, mCode %d, uni %c, qtKeyCode %d\n", code, mCode, unicode, qtKeyCode);
+
+    // Handle map changes based on press/release of modifiers
+    // hardcoded for now
+    int modif = -1;
+    switch (qtKeyCode)
+    {
+        case Qt::Key_Alt:
+        case Qt::Key_F22:
+            modif = (1<<KG_ALT);
+            break;
+        case Qt::Key_Control:
+            modif = (1<<KG_CTRL);
+            break;
+        case Qt::Key_Shift:
+            modif = (1<<KG_SHIFT);
+            break;
+        case Qt::Key_Left:
+        case Qt::Key_Right:
+        case Qt::Key_Up:
+        case Qt::Key_Down:
+            if (qt_screen->isTransformed())
+                qtKeyCode = xform_dirkey(qtKeyCode);
+            break;
+    }
+
+    if (modif != -1) {
+        if (release)
+            current_map &= ~modif;
+        else
+            current_map |= modif;
+    }
+
+    unsigned int uni = unicode;
+    processKeyEvent(uni & 0xff, qtKeyCode, map_to_modif(current_map), !release, 0);
+}
 
 /* USB driver */