├── .gitignore ├── README.md ├── doc ├── kvkbd.png ├── config-menu.png ├── CMakeLists.txt └── index.docbook ├── kvkbd.kdev4 ├── pics ├── tray.png └── CMakeLists.txt ├── src ├── Messages.sh ├── resources.qrc ├── org.kde.kvkbd.Dock.xml ├── keysymconvert.h ├── org.kde.kvkbd.Kvkbd.xml ├── resizabledragwidget.h ├── mainwidget.h ├── dragwidget.h ├── vkeyboard.cpp ├── CMakeLists.txt ├── kbdtray.h ├── vbutton.h ├── kbddock.h ├── x11keyboard.h ├── vkeyboard.h ├── kbdtray.cpp ├── kvkbd.desktop ├── themeloader.h ├── standart.css ├── dragwidget.cpp ├── kbddock.cpp ├── kvkbdapp.h ├── resizabledragwidget.cpp ├── main.cpp ├── vbutton.cpp ├── mainwidget.cpp ├── x11keyboard.cpp ├── standart.xml ├── kvkbdapp.cpp ├── themeloader.cpp └── keysymconvert.cpp ├── .arcconfig ├── AUTHORS ├── themes ├── CMakeLists.txt └── standart.xml ├── colors ├── CMakeLists.txt ├── legacy.css ├── light.css ├── dark.css └── simple.css ├── TODO ├── CMakeLists.txt ├── INSTALL ├── README ├── ChangeLog └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .kdev4 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | kvkbd 2 | ===== 3 | 4 | Virtual Keyboard for KDE 5 | -------------------------------------------------------------------------------- /doc/kvkbd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kvkbd/HEAD/doc/kvkbd.png -------------------------------------------------------------------------------- /kvkbd.kdev4: -------------------------------------------------------------------------------- 1 | [Project] 2 | Manager=KDevCMakeManager 3 | Name=kvkbd 4 | -------------------------------------------------------------------------------- /pics/tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kvkbd/HEAD/pics/tray.png -------------------------------------------------------------------------------- /src/Messages.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | $XGETTEXT *.cpp -o $podir/kvkbd.pot 3 | -------------------------------------------------------------------------------- /.arcconfig: -------------------------------------------------------------------------------- 1 | { 2 | "phabricator.uri" : "https://phabricator.kde.org/" 3 | } 4 | -------------------------------------------------------------------------------- /doc/config-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kvkbd/HEAD/doc/config-menu.png -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Todor Gyumyushev 2 | Guillaume Martres 3 | -------------------------------------------------------------------------------- /pics/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install( FILES tray.png DESTINATION ${DATA_INSTALL_DIR}/kvkbd/pics) 2 | -------------------------------------------------------------------------------- /themes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install( FILES standart.xml DESTINATION ${DATA_INSTALL_DIR}/kvkbd/themes) 2 | -------------------------------------------------------------------------------- /colors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install( FILES dark.css legacy.css light.css simple.css DESTINATION ${DATA_INSTALL_DIR}/kvkbd/colors) 2 | -------------------------------------------------------------------------------- /src/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | standart.xml 4 | standart.css 5 | 6 | 7 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ########### install files ############### 2 | # 3 | kde4_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kvkbd) 4 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - Use layouts instead of manually setting each button position? 2 | - Make the colorscheme configurable? 3 | - Write user and dev doc, comment code 4 | - Use system-wide config file for loginhelper mode? 5 | - various FIXMEs and TODOs in the code 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.4) 2 | project( kvkbd ) 3 | 4 | find_package(KDE4 REQUIRED) 5 | 6 | include (KDE4Defaults) 7 | 8 | add_subdirectory( doc ) 9 | add_subdirectory( src ) 10 | add_subdirectory( pics ) 11 | add_subdirectory( colors ) 12 | add_subdirectory( themes ) -------------------------------------------------------------------------------- /src/org.kde.kvkbd.Dock.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /colors/legacy.css: -------------------------------------------------------------------------------- 1 | QWidget[name="main"] { 2 | background-color:black; 3 | border-radius: 5px 5px 5px 5px; 4 | } 5 | 6 | VButton[action="toggleExtension"] { 7 | background-color:gray; 8 | border-color: gray; 9 | } 10 | VButton[action="toggleVisibility"] { 11 | background-color:red; 12 | border-color:red; 13 | } -------------------------------------------------------------------------------- /src/keysymconvert.h: -------------------------------------------------------------------------------- 1 | /* $XFree86: xc/programs/xterm/keysym2ucs.h,v 1.1 1999/06/12 15:37:18 dawes Exp $ */ 2 | /* 3 | * This module converts keysym values into the corresponding ISO 10646-1 4 | * (UCS, Unicode) values. 5 | */ 6 | 7 | #ifndef KEYSYM2UCS_H 8 | #define KEYSYM2UCS_H 9 | 10 | #include 11 | 12 | class KeySymConvert 13 | { 14 | public: 15 | long convert(KeySym keysym); 16 | }; 17 | 18 | #endif // KEYSYM2UCS_H 19 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Kvkbd - A virtual keyboard for KDE4 2 | =============================================================================== 3 | Dependencies: 4 | - cmake 5 | - kdelibs headers 6 | - libxtst (X11 Record extension library) 7 | 8 | On Debian systems, this can be installed with: 9 | sudo aptitude install cmake kdelibs5-dev libxtst-dev 10 | 11 | Build instructions: 12 | mkdir build 13 | cd build 14 | cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=$(kde-config --prefix) .. 15 | make 16 | Then, as root using sudo or su: 17 | make install 18 | -------------------------------------------------------------------------------- /src/org.kde.kvkbd.Kvkbd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/resizabledragwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef RESIZABLEDRAGWIDGET_H 2 | #define RESIZABLEDRAGWIDGET_H 3 | 4 | #include "dragwidget.h" 5 | 6 | class ResizableDragWidget : public DragWidget 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | explicit ResizableDragWidget(QWidget *parent = 0); 12 | ~ResizableDragWidget(); 13 | 14 | 15 | 16 | 17 | protected: 18 | virtual void mouseMoveEvent(QMouseEvent * e); 19 | virtual void mousePressEvent(QMouseEvent * e); 20 | virtual void mouseReleaseEvent(QMouseEvent * e); 21 | virtual void paintEvent(QPaintEvent *e); 22 | 23 | bool doResize; 24 | }; 25 | 26 | 27 | 28 | #endif // RESIZABLEDRAGWIDGET_H 29 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Kvkbd - A virtual keyboard for KDE4 2 | =============================================================================== 3 | Installations instructions: 4 | See INSTALL 5 | 6 | Known issues: 7 | - The mod keys(ctrl, alt, alt gr, pg up, pg down, ...) may not work if you're 8 | not using Xserver >= 1.5 with evdev enabled due to changes in the keys mapping. 9 | Hopefully, new releases of Kvkbd will detect which mapping is used and behave 10 | accordingly. 11 | - The Loginhelper mode(see manual) does not work currently with KDM, you can either 12 | apply the patch for KDM available here: , 13 | wait for your distribution or for KDE to include the patch, or use XDM. 14 | -------------------------------------------------------------------------------- /src/mainwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWIDGET_H 2 | #define MAINWIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vkeyboard.h" 11 | 12 | 13 | class MainWidget : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWidget(QWidget *parent = 0); 19 | void setBaseSize(int w, int h); 20 | 21 | signals: 22 | 23 | public slots: 24 | void textSwitch(bool); 25 | void updateLayout(int index, QString layout_name); 26 | void updateGroupState(const ModifierGroupStateMap&); 27 | void updateFont(const QFont& widgetFont); 28 | 29 | protected: 30 | virtual void resizeEvent(QResizeEvent *ev); 31 | QSize bsize; 32 | 33 | }; 34 | 35 | #endif // MAINWIDGET_H 36 | -------------------------------------------------------------------------------- /src/dragwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAGWIDGET_H 2 | #define DRAGWIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class DragWidget : public QWidget 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | DragWidget(QWidget *parent = 0); 14 | ~DragWidget(); 15 | 16 | public slots: 17 | void toggleVisibility(); 18 | void blurBackground(bool blurEnabled); 19 | void setLocked(bool mode); 20 | bool isLocked(); 21 | 22 | protected: 23 | virtual void mouseMoveEvent(QMouseEvent * e); 24 | virtual void mousePressEvent(QMouseEvent * e); 25 | virtual void mouseReleaseEvent(QMouseEvent * e); 26 | 27 | virtual void paintEvent(QPaintEvent *e); 28 | 29 | 30 | QPoint dragPoint; 31 | QPoint gpress; 32 | 33 | bool dragged; 34 | bool moved; 35 | bool locked; 36 | 37 | signals: 38 | void widgetShown(); 39 | }; 40 | 41 | 42 | #endif // DRAGWIDGET_H 43 | -------------------------------------------------------------------------------- /colors/light.css: -------------------------------------------------------------------------------- 1 | QWidget[name="main"] { 2 | background-color:rgba(255,255,255,30%); 3 | border-radius: 5px 5px 5px 5px; 4 | } 5 | 6 | VButton { 7 | 8 | margin:1px; 9 | padding:0px; 10 | border-style: outset; 11 | border-radius: 5px; 12 | border-width: 1px; 13 | 14 | font-size:13px; 15 | font-weight:bold; 16 | 17 | border-color: #000000; 18 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #FFFFFF, stop: 1 #999999 ); 19 | 20 | color:black; 21 | } 22 | 23 | VButton:pressed { 24 | 25 | border-style: inset; 26 | } 27 | VButton:checked { 28 | 29 | border-style: inset; 30 | border-width:2px; 31 | } 32 | VButton:hover { 33 | border-width:2px; 34 | border-color: #555555; 35 | } 36 | VButton[action="toggleExtension"] { 37 | background-color:gray; 38 | border-color: gray; 39 | } 40 | VButton[action="toggleVisibility"] { 41 | background-color:red; 42 | border-color:red; 43 | } 44 | -------------------------------------------------------------------------------- /colors/dark.css: -------------------------------------------------------------------------------- 1 | QWidget[name="main"] { 2 | background-color:rgba(0,0,0,30%); 3 | border-radius: 5px 5px 5px 5px; 4 | } 5 | 6 | VButton { 7 | 8 | margin:1px; 9 | padding:0px; 10 | border-style: outset; 11 | border-radius: 5px; 12 | border-width: 1px; 13 | 14 | font-size:13px; 15 | font-weight:bold; 16 | 17 | border-color: #000000; 18 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #000000, stop: 1 #555555); 19 | 20 | color:#cccccc; 21 | } 22 | 23 | VButton:pressed { 24 | 25 | border-style: inset; 26 | } 27 | VButton:checked { 28 | 29 | border-style: inset; 30 | border-width: 2px; 31 | border-color: #999999; 32 | } 33 | VButton:hover { 34 | border-width:2px; 35 | border-color: #555555; 36 | } 37 | 38 | VButton[action="toggleExtension"] { 39 | background-color:gray; 40 | border-color: gray; 41 | } 42 | VButton[action="toggleVisibility"] { 43 | background-color:red; 44 | border-color:red; 45 | } -------------------------------------------------------------------------------- /colors/simple.css: -------------------------------------------------------------------------------- 1 | QWidget[name="main"] { 2 | background-color:rgba(255,255,255,12%); 3 | 4 | } 5 | 6 | VButton { 7 | 8 | margin:2px; 9 | padding:0px; 10 | border-style: outset; 11 | 12 | border-width: 1px; 13 | 14 | font-size:13px; 15 | font-weight:bold; 16 | background-color:rgba(172,172,172,70%); 17 | border-color: #000000; 18 | /* background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #FFFFFF, stop: 1 #999999 ); */ 19 | 20 | color:black; 21 | } 22 | 23 | VButton:pressed { 24 | 25 | border-style: inset; 26 | border-color: #333333; 27 | } 28 | VButton:checked { 29 | 30 | /* border-style: inset; */ 31 | border-width:2px; 32 | border-color: #333333; 33 | } 34 | VButton:hover { 35 | border-width:2px; 36 | border-color: #333333; 37 | 38 | } 39 | VButton[action="toggleExtension"] { 40 | background-color:gray; 41 | border-color: gray; 42 | } 43 | VButton[action="toggleVisibility"] { 44 | background-color:red; 45 | border-color:red; 46 | } 47 | -------------------------------------------------------------------------------- /src/vkeyboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor Gyumyushev 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #include "vkeyboard.h" 21 | 22 | VKeyboard::VKeyboard(QObject *parent) : QObject(parent) 23 | { 24 | 25 | } 26 | 27 | VKeyboard::~VKeyboard() 28 | { 29 | } 30 | 31 | #include "vkeyboard.moc" 32 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(KDE4 REQUIRED) 2 | find_package(Qt4 COMPONENTS QtGui QtCore QtXml REQUIRED) 3 | find_package(LibXslt REQUIRED) 4 | 5 | include(${QT_USE_FILE}) 6 | 7 | include_directories( ${KDE4_INCLUDES} ${QT_INCLUDES} ) 8 | 9 | set(kvkbd_SRCS vkeyboard.cpp 10 | x11keyboard.cpp 11 | dragwidget.cpp 12 | mainwidget.cpp 13 | vbutton.cpp 14 | main.cpp 15 | resizabledragwidget.cpp 16 | keysymconvert.cpp 17 | kbddock.cpp 18 | kvkbdapp.cpp 19 | kbdtray.cpp 20 | themeloader.cpp 21 | ) 22 | 23 | 24 | 25 | SET(kvkbd_RESOURCES resources.qrc) 26 | 27 | 28 | QT4_ADD_RESOURCES(kvkbd_RESOURCES_RCC ${kvkbd_RESOURCES}) 29 | 30 | QT4_ADD_DBUS_ADAPTOR(kvkbd_SRCS org.kde.kvkbd.Kvkbd.xml 31 | mainwidget.h MainWidget) 32 | 33 | QT4_ADD_DBUS_ADAPTOR(kvkbd_SRCS org.kde.kvkbd.Dock.xml 34 | kbddock.h KbdDock) 35 | 36 | kde4_add_executable(kvkbd ${kvkbd_SRCS} ${kvkbd_RC_SRCS} ${kvkbd_RESOURCES_RCC}) 37 | 38 | target_link_libraries(kvkbd ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS} ${QT_LIBRARIES} X11 Xtst) 39 | 40 | 41 | install(TARGETS kvkbd ${INSTALL_TARGETS_DEFAULT_ARGS}) 42 | 43 | install( FILES kvkbd.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) 44 | -------------------------------------------------------------------------------- /src/kbdtray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2014 Todor Gyumyushev 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | * 17 | */ 18 | 19 | #ifndef KBDTRAY_H 20 | #define KBDTRAY_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | class KbdTray : public KSystemTrayIcon 28 | { 29 | Q_OBJECT 30 | 31 | public: 32 | explicit KbdTray(QWidget* parent = 0); 33 | ~KbdTray(); 34 | QMenu* getContextMenu(); 35 | 36 | public slots: 37 | void activationHandler(QSystemTrayIcon::ActivationReason reason); 38 | 39 | 40 | signals: 41 | void requestVisibility(); 42 | 43 | }; 44 | 45 | 46 | #endif // KBDTRAY_H 47 | -------------------------------------------------------------------------------- /src/vbutton.h: -------------------------------------------------------------------------------- 1 | #ifndef VBUTTON_H 2 | #define VBUTTON_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "x11keyboard.h" 12 | 13 | class VButton : public QPushButton 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit VButton(QWidget *parent = 0); 19 | 20 | void storeSize(); 21 | 22 | void reposition(const QSize &baseSize, const QSize &size); 23 | QRect VRect(); 24 | 25 | unsigned int getKeyCode(); 26 | void setKeyCode(unsigned int keyCode); 27 | 28 | void setButtonText(const ButtonText& text); 29 | ButtonText buttonText() const; 30 | 31 | void setTextIndex(int index); 32 | int textIndex(); 33 | void updateText(); 34 | void nextText(); 35 | void setCaps(bool mode); 36 | void setShift(bool mode); 37 | 38 | signals: 39 | void keyClick(unsigned int); 40 | void buttonAction(const QString& action); 41 | 42 | public slots: 43 | void sendKey(); 44 | 45 | protected: 46 | unsigned int keyCode; 47 | QRect vpos; 48 | 49 | bool rightClicked; 50 | QTimer *keyTimer; 51 | 52 | 53 | ButtonText mButtonText; 54 | int mTextIndex; 55 | 56 | bool isCaps; 57 | bool isShift; 58 | 59 | static int RepeatShortDelay; 60 | static int RepeatLongDelay; 61 | 62 | protected slots: 63 | void mousePressEvent(QMouseEvent *e); 64 | void mouseReleaseEvent(QMouseEvent *e); 65 | void repeatKey(); 66 | 67 | 68 | }; 69 | 70 | #endif // VBUTTON_H 71 | -------------------------------------------------------------------------------- /src/kbddock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef KBDDOCK_H 23 | #define KBDDOCK_H 24 | 25 | #include "dragwidget.h" 26 | 27 | #include 28 | #include 29 | 30 | 31 | class KbdDock : public DragWidget 32 | { 33 | Q_OBJECT 34 | 35 | 36 | public: 37 | KbdDock(const WId& window); 38 | ~KbdDock(); 39 | 40 | void paintEvent(QPaintEvent *); 41 | void setPixmap(const QPixmap& pm); 42 | 43 | signals: 44 | void requestVisibility(); 45 | 46 | 47 | protected: 48 | void mouseReleaseEvent(QMouseEvent *ev); 49 | WId wID; 50 | 51 | QPixmap pm; 52 | 53 | }; 54 | 55 | #endif // KBDDOCK_H 56 | -------------------------------------------------------------------------------- /src/x11keyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor Gyumyushev 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #ifndef X11KEYBOARD_H 21 | #define X11KEYBOARD_H 22 | 23 | #include "keysymconvert.h" 24 | #include 25 | 26 | #include "vkeyboard.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | 36 | class X11Keyboard : public VKeyboard 37 | { 38 | Q_OBJECT 39 | 40 | public: 41 | X11Keyboard(QObject *parent=0); 42 | virtual ~X11Keyboard(); 43 | void textForKeyCode(unsigned int keyCode, ButtonText& text); 44 | 45 | public slots: 46 | virtual void processKeyPress(unsigned int); 47 | virtual void queryModState(); 48 | virtual void constructLayouts(); 49 | virtual void layoutChanged(); 50 | virtual void start(); 51 | 52 | protected: 53 | 54 | void sendKey(unsigned int keycode); 55 | 56 | QStringList layouts; 57 | int layout_index; 58 | 59 | KeySymConvert kconvert; 60 | 61 | 62 | bool queryModKeyState(KeySym keyCode); 63 | ModifierGroupStateMap groupState; 64 | QTimer *groupTimer; 65 | 66 | }; 67 | 68 | #endif // X11KEYBOARD_H 69 | -------------------------------------------------------------------------------- /src/vkeyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #ifndef VKEYBOARD_H 21 | #define VKEYBOARD_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | //caps state, numlock state 30 | typedef QMap ModifierGroupStateMap; 31 | typedef QMapIterator ModifierGroupStateMapIterator; 32 | //normal text, shift text 33 | typedef QList ButtonText; 34 | 35 | class VKeyboard : public QObject 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | VKeyboard(QObject *parent=0); 41 | virtual ~VKeyboard(); 42 | 43 | virtual void textForKeyCode(unsigned int keyCode, ButtonText& text)=0; 44 | 45 | public slots: 46 | virtual void processKeyPress(unsigned int)=0; 47 | virtual void queryModState()=0; 48 | virtual void constructLayouts()=0; 49 | virtual void layoutChanged()=0; 50 | virtual void start()=0; 51 | 52 | signals: 53 | //key sent successfully 54 | void keyProcessComplete(unsigned int); 55 | 56 | void groupStateChanged(const ModifierGroupStateMap& modifier_state); 57 | 58 | //layout index in list, layout caption 59 | void layoutUpdated(int, QString); 60 | }; 61 | 62 | #endif // VKEYBOARD_H 63 | -------------------------------------------------------------------------------- /src/kbdtray.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "kbdtray.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | // TODO: find a way to hide the widget before asking for quit 36 | KbdTray::KbdTray(QWidget* parent) : KSystemTrayIcon(parent) 37 | { 38 | setObjectName("KvkbdTray"); 39 | setIcon(UserIcon("tray")); 40 | 41 | QAction *titleAction = contextMenuTitle(); 42 | titleAction->setText("Kvkbd"); 43 | 44 | connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activationHandler(QSystemTrayIcon::ActivationReason))); 45 | 46 | } 47 | 48 | KbdTray::~KbdTray() 49 | { 50 | 51 | } 52 | 53 | 54 | 55 | 56 | QMenu* KbdTray::getContextMenu() 57 | { 58 | return this->contextMenu(); 59 | 60 | } 61 | void KbdTray::activationHandler(QSystemTrayIcon::ActivationReason reason) 62 | { 63 | if (reason == QSystemTrayIcon::Trigger) { 64 | emit requestVisibility(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/kvkbd.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Kvkbd 3 | Name[ast]=Kvkbd 4 | Name[bs]=Kvkbd 5 | Name[cs]=Kvkbd 6 | Name[de]=Kvkbd 7 | Name[es]=Kvkbd 8 | Name[fi]=Kvkbd 9 | Name[fr]=Kvkbd 10 | Name[gl]=Kvkbd 11 | Name[hu]=Kvkbd 12 | Name[nl]=Kvkbd 13 | Name[nn]=Kvkbd 14 | Name[pl]=Kvkbd 15 | Name[pt]=Kvkbd 16 | Name[pt_BR]=Kvkbd 17 | Name[sk]=Kvkbd 18 | Name[sv]=Kvkbd 19 | Name[uk]=Kvkbd 20 | Name[x-test]=xxKvkbdxx 21 | Exec=kvkbd 22 | Icon=preferences-desktop-keyboard 23 | Type=Application 24 | Comment=A virtual keyboard for KDE 25 | Comment[bs]=Virtuelna tastatura za KDE 26 | Comment[cs]=Virtuální klávesnice pro KDE 27 | Comment[de]=Eine virtuelle Tastatur für KDE 28 | Comment[es]=Un teclado virtual para KDE 29 | Comment[fi]=KDE:n virtuaalinäppäimistö 30 | Comment[fr]=Un clavier virtuel pour KDE 31 | Comment[gl]=Un teclado virtual para KDE. 32 | Comment[hu]=Virtuális billentyűzet a KDE-hez 33 | Comment[nl]=Een virtueel toetsenbord voor KDE 34 | Comment[nn]=Virtuelt tastatur frå KDE 35 | Comment[pl]=Wirtualna klawiatura dla KDE 36 | Comment[pt]=Um teclado virtual para o KDE 37 | Comment[pt_BR]=Um teclado virtual para o KDE 38 | Comment[sk]=Virtuálna klávesnica pre KDE 39 | Comment[sv]=Ett virtuellt tangentbord för KDE 40 | Comment[uk]=Віртуальна клавіатура для KDE 41 | Comment[x-test]=xxA virtual keyboard for KDExx 42 | GenericName=Virtual Keyboard 43 | GenericName[bs]=Virtuelna tastatura 44 | GenericName[cs]=Virtuální klávesnice 45 | GenericName[de]=Virtuelle Tastatur 46 | GenericName[es]=Teclado virtual 47 | GenericName[fi]=Virtuaalinäppäimistö 48 | GenericName[fr]=Clavier virtuel 49 | GenericName[gl]=Teclado virtual 50 | GenericName[hu]=Virtuális billentyűzet 51 | GenericName[nl]=Virtueel toetsenbord 52 | GenericName[nn]=Virtuelt tastatur 53 | GenericName[pl]=Wirtualna klawiatura 54 | GenericName[pt]=Teclado Virtual 55 | GenericName[pt_BR]=Teclado virtual 56 | GenericName[sk]=Virtuálna klávesnica 57 | GenericName[sv]=Virtuellt tangentbord 58 | GenericName[uk]=Віртуальна клавіатура 59 | GenericName[x-test]=xxVirtual Keyboardxx 60 | Categories=Qt;KDE;Utility;Accessibility; 61 | Terminal=false 62 | 63 | -------------------------------------------------------------------------------- /src/themeloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #ifndef THEMELOADER_H 21 | #define THEMELOADER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "mainwidget.h" 31 | #include "vbutton.h" 32 | 33 | 34 | class ThemeLoader : public QObject 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | ThemeLoader(QWidget *parent); 40 | ~ThemeLoader(); 41 | 42 | void loadTheme(QString& themeName); 43 | 44 | 45 | void loadColorFile(const QString& fileName); 46 | 47 | int loadLayout(const QString& themeName, const QString& path); 48 | 49 | void findColorStyles(QMenu *parent, const QString& selectedStyle); 50 | 51 | protected: 52 | void loadKeys(MainWidget *vPart, const QDomNode& wNode); 53 | bool applyProperty(VButton *btn, const QString& attributeName, QDomNamedNodeMap *attributes, QVariant defaultValue=""); 54 | 55 | QMap widthMap; 56 | QMap heightMap; 57 | QMap spacingMap; 58 | 59 | public slots: 60 | void loadColorStyle(); 61 | 62 | signals: 63 | 64 | void partLoaded(MainWidget *vPart, int total_rows, int total_cols); 65 | void buttonLoaded(VButton *btn); 66 | void colorStyleChanged(); 67 | }; 68 | 69 | #endif // THEMELOADER_H 70 | -------------------------------------------------------------------------------- /src/standart.css: -------------------------------------------------------------------------------- 1 | QWidget[name="main"] { 2 | background-color:rgba(0,0,0,20%); 3 | 4 | } 5 | 6 | VButton { 7 | 8 | margin:1px; 9 | padding:0px; 10 | border-style: outset; 11 | border-radius: 5px; 12 | border-width: 1px; 13 | 14 | font-size:13px; 15 | font-weight:bold; 16 | 17 | } 18 | 19 | VButton:pressed { 20 | 21 | border-style: inset; 22 | } 23 | VButton:checked { 24 | 25 | border-style: inset; 26 | border-width:2px; 27 | } 28 | VButton:hover { 29 | border-width:2px; 30 | } 31 | 32 | VButton[colorGroup="normal"] { 33 | border-color: #97c5d5; 34 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #97c5d5, stop: 1 #c7f5f5); 35 | 36 | } 37 | VButton[colorGroup="system"] { 38 | border-color: #e8a8a5; 39 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #e8a8a5, stop: 1 #f8c8c5); 40 | } 41 | VButton[colorGroup="application"] { 42 | border-color: #a97ca9; 43 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #a97ca9, stop: 1 #a97ca9); 44 | } 45 | VButton[colorGroup="function"] { 46 | border-color: #edc07d; 47 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #edc07d, stop: 1 #edc07d); 48 | } 49 | VButton[colorGroup="enter"] { 50 | border-color: #f1efbe; 51 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #f1efbe, stop: 1 #f1efbe); 52 | } 53 | VButton[colorGroup="cursor"] { 54 | border-color: #a8d1b1; 55 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #a8d1b1, stop: 1 #a8d1b1); 56 | } 57 | VButton[colorGroup="other"] { 58 | border-color: #999999; 59 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #ffffff, stop: 1 #fefefe); 60 | } 61 | VButton[colorGroup="numeric"] { 62 | border-color: #9faaca; 63 | background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #9faaca, stop: 1 #9faaca); 64 | } 65 | VButton[action="toggleExtension"] { 66 | background-color:gray; 67 | border-color: gray; 68 | } 69 | VButton[action="toggleVisibility"] { 70 | background-color:red; 71 | border-color:red; 72 | } 73 | VButton[colorGroup="nextLayout"] { 74 | background-color:none; 75 | border:none; 76 | } 77 | -------------------------------------------------------------------------------- /src/dragwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "dragwidget.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | using namespace std; 10 | 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | 18 | DragWidget::DragWidget(QWidget *parent) : 19 | QWidget(parent), dragged(false), moved(false), locked(false) 20 | { 21 | setAttribute(Qt::WA_TranslucentBackground); 22 | } 23 | 24 | DragWidget::~DragWidget() 25 | { 26 | 27 | } 28 | 29 | void DragWidget::blurBackground(bool blurEnabled) 30 | { 31 | this->setProperty("blurBackground", QVariant(blurEnabled)); 32 | 33 | Display *dpy = QX11Info::display(); 34 | Atom net_wm_blur_region = XInternAtom(dpy, "_KDE_NET_WM_BLUR_BEHIND_REGION", False); 35 | 36 | if (blurEnabled) { 37 | 38 | XChangeProperty(dpy, this->winId(), net_wm_blur_region, XA_CARDINAL, 32, PropModeReplace, 0, 0); 39 | 40 | } 41 | else { 42 | XDeleteProperty(dpy, this->winId(), net_wm_blur_region); 43 | 44 | } 45 | repaint(); 46 | } 47 | void DragWidget::setLocked(bool locked) 48 | { 49 | this->locked = locked; 50 | } 51 | bool DragWidget::isLocked() 52 | { 53 | return locked; 54 | } 55 | 56 | void DragWidget::mousePressEvent(QMouseEvent *e) 57 | { 58 | 59 | if (locked) { 60 | return; 61 | } 62 | 63 | gpress = e->globalPos(); 64 | dragged = true; 65 | dragPoint = e->pos(); 66 | 67 | 68 | 69 | } 70 | 71 | void DragWidget::mouseMoveEvent(QMouseEvent *ev) 72 | { 73 | 74 | 75 | if (!dragged) return; 76 | 77 | moved=true; 78 | 79 | QPoint curr(ev->globalPos().x() - dragPoint.x(), ev->globalPos().y() - dragPoint.y()); 80 | move(curr); 81 | 82 | } 83 | 84 | void DragWidget::mouseReleaseEvent(QMouseEvent *) 85 | { 86 | 87 | dragged = false; 88 | moved = false; 89 | } 90 | 91 | void DragWidget::paintEvent(QPaintEvent *) 92 | { 93 | QStyleOption opt; 94 | opt.initFrom(this); 95 | QStylePainter p(this); 96 | p.drawPrimitive(QStyle::PE_Widget, opt); 97 | } 98 | 99 | void DragWidget::toggleVisibility() 100 | { 101 | if (isMinimized()) { 102 | showNormal(); 103 | show(); 104 | raise(); 105 | } 106 | else { 107 | showMinimized(); 108 | hide(); 109 | lower(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/kbddock.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #include "kbddock.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include "dockadaptor.h" 33 | 34 | #include 35 | using namespace std; 36 | 37 | #define DEFAULT_WIDTH 105 38 | #define DEFAULT_HEIGHT 35 39 | 40 | KbdDock::KbdDock(const WId& window) : DragWidget(0), wID(window) 41 | { 42 | 43 | setAttribute(Qt::WA_AlwaysShowToolTips); 44 | setAttribute(Qt::WA_DeleteOnClose, false); 45 | 46 | setWindowFlags( Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint ); 47 | 48 | setFocusPolicy(Qt::NoFocus); 49 | 50 | setToolTip(i18nc("@info:tooltip Displayed on the movable dock", "Toggle keyboard visibility")); 51 | 52 | 53 | 54 | resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 55 | 56 | raise(); 57 | } 58 | 59 | KbdDock::~KbdDock() 60 | { 61 | 62 | 63 | } 64 | 65 | void KbdDock::paintEvent(QPaintEvent *) 66 | { 67 | 68 | QPixmap pix = QPixmap::grabWindow(wID); 69 | 70 | QPainter p(this); 71 | 72 | p.drawPixmap(0, 0, pix.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); 73 | 74 | } 75 | 76 | 77 | 78 | void KbdDock::mouseReleaseEvent(QMouseEvent *ev) 79 | { 80 | 81 | if (dragged && !moved) { 82 | emit requestVisibility(); 83 | } 84 | 85 | DragWidget::mouseReleaseEvent(ev); 86 | raise(); 87 | } 88 | -------------------------------------------------------------------------------- /src/kvkbdapp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #ifndef KVKBDAPP_H 21 | #define KVKBDAPP_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "resizabledragwidget.h" 31 | #include "mainwidget.h" 32 | #include "kbdtray.h" 33 | #include "vbutton.h" 34 | #include "themeloader.h" 35 | #include "kbddock.h" 36 | #include "vkeyboard.h" 37 | 38 | class KvkbdApp : public KUniqueApplication 39 | { 40 | Q_OBJECT 41 | 42 | public: 43 | KvkbdApp(bool loginhelper=false); 44 | ~KvkbdApp(); 45 | 46 | 47 | 48 | public slots: 49 | void keyProcessComplete(unsigned int); 50 | 51 | void buttonAction(const QString& action); 52 | void storeConfig(); 53 | void toggleExtension(); 54 | 55 | void chooseFont(); 56 | void autoResizeFont(bool mode); 57 | void setStickyModKeys(bool mode); 58 | 59 | 60 | void partLoaded(MainWidget *vPart, int total_rows, int total_cols); 61 | void buttonLoaded(VButton *btn); 62 | 63 | 64 | 65 | protected: 66 | 67 | ResizableDragWidget *widget; 68 | 69 | KbdTray *tray; 70 | 71 | 72 | QMap colorMap; 73 | QMap parts; 74 | QMap layoutPosition; 75 | 76 | QSignalMapper *signalMapper; 77 | 78 | 79 | QGridLayout *layout; 80 | 81 | 82 | QMap actionButtons; 83 | 84 | ThemeLoader *themeLoader; 85 | 86 | KbdDock *dock; 87 | 88 | VKeyboard *xkbd; 89 | 90 | bool is_login; 91 | 92 | signals: 93 | void textSwitch(bool); 94 | void fontUpdated(const QFont& font); 95 | void startupCompleted(); 96 | }; 97 | 98 | #endif // KVKBDAPP_H 99 | -------------------------------------------------------------------------------- /src/resizabledragwidget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "resizabledragwidget.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | 29 | #include 30 | using namespace std; 31 | 32 | ResizableDragWidget::ResizableDragWidget(QWidget *parent) : 33 | DragWidget(parent), doResize(false) 34 | { 35 | 36 | 37 | } 38 | 39 | ResizableDragWidget::~ResizableDragWidget() 40 | { 41 | } 42 | 43 | void ResizableDragWidget::mousePressEvent(QMouseEvent * ev) 44 | { 45 | // cout << "ResizableDragWidget::mousePressEvent" << endl; 46 | 47 | DragWidget::mousePressEvent(ev); 48 | 49 | if (dragPoint.x() > width() - 20 && dragPoint.x() < width() && dragPoint.y() > height() - 20 && dragPoint.y() < height()) { 50 | 51 | dragPoint = QPoint(width() - ev->pos().x(), height() - ev->pos().y()); 52 | 53 | dragged = false; 54 | doResize = true; 55 | } 56 | 57 | } 58 | 59 | void ResizableDragWidget::mouseMoveEvent(QMouseEvent * ev) 60 | { 61 | // cout << "ResizableDragWidget::mouseMoveEvent | Resize: " << doResize << " | Dragged: " << dragged << endl; 62 | 63 | 64 | DragWidget::mouseMoveEvent(ev); 65 | 66 | if (!doResize) return; 67 | 68 | QPoint curr(ev->globalPos().x(), ev->globalPos().y()); 69 | QPoint pos = QWidget::pos(); 70 | int nw = curr.x() - pos.x() + dragPoint.x(); 71 | int nh = curr.y() - pos.y() + dragPoint.y(); 72 | 73 | resize(nw, nh); 74 | 75 | } 76 | 77 | void ResizableDragWidget::mouseReleaseEvent(QMouseEvent * e) 78 | { 79 | DragWidget::mouseReleaseEvent(e); 80 | 81 | doResize = false; 82 | 83 | } 84 | 85 | void ResizableDragWidget::paintEvent(QPaintEvent *ev) 86 | { 87 | 88 | DragWidget::paintEvent(ev); 89 | 90 | QPainter p(this); 91 | 92 | for (int a = 0; a < 20; a += 4) { 93 | 94 | p.setPen(QColor(170, 170, 170)); 95 | p.drawLine(width() - 20 + a, height() - 2, width() - 2, height() - 20 + a); 96 | p.setPen(QColor(200, 200, 200)); 97 | p.drawLine(width() - 19 + a, height() - 2, width() - 2, height() - 19 + a); 98 | } 99 | 100 | } 101 | 102 | 103 | 104 | #include "resizabledragwidget.moc" 105 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | 23 | 24 | #include "kvkbdapp.h" 25 | #include 26 | #include 27 | 28 | static const char description[] = 29 | I18N_NOOP("A virtual keyboard for KDE"); 30 | 31 | static const char version[] = "0.7.2"; 32 | 33 | #include 34 | 35 | void findLoginWindow() 36 | { 37 | unsigned int numkids, i,mapped,scrn; 38 | Window r, p; 39 | Window *kids=0; 40 | //XWindowAttributes attr; 41 | Window root; 42 | Display *dipsy=0; 43 | char *win_name=0; 44 | 45 | dipsy = XOpenDisplay(0); 46 | if (!dipsy)return; 47 | 48 | scrn = DefaultScreen(dipsy); 49 | root = RootWindow(dipsy, scrn); 50 | 51 | mapped = 0; 52 | XQueryTree(dipsy, root, &r, &p, &kids, &numkids); 53 | 54 | 55 | for (i = 0; i < numkids; ++i) 56 | { 57 | XFetchName(dipsy, kids[i], &win_name); 58 | QString c(win_name); 59 | 60 | if (c=="kvkbd.login") 61 | { 62 | long wid = kids[i]; 63 | XDestroyWindow(dipsy,wid); 64 | XFlush(dipsy); 65 | i=numkids; 66 | } 67 | XFree(win_name); 68 | } 69 | XCloseDisplay(dipsy); 70 | } 71 | 72 | int main(int argc, char **argv) 73 | { 74 | 75 | KAboutData about("kvkbd", 0, ki18n("Kvkbd"), version, ki18n(description), 76 | KAboutData::License_LGPL_V3, ki18n("(C) 2007-2014 The Kvkbd Developers")); 77 | about.addAuthor(ki18n("Todor Gyumyushev"), ki18n("Original Author"), "yodor1@gmail.com"); 78 | about.addAuthor(ki18n("Guillaume Martres"), ki18n("KDE4 port"), "smarter@ubuntu.com"); 79 | about.setProgramIconName("preferences-desktop-keyboard"); 80 | 81 | KCmdLineArgs::init(argc, argv, &about); 82 | KCmdLineOptions options; 83 | 84 | options.add("loginhelper", ki18n("Stand alone version for use with KDM or XDM.\n" 85 | "See Kvkbd Handbook for information on how to use this option.")); 86 | KCmdLineArgs::addCmdLineOptions(options); 87 | 88 | bool is_login = KCmdLineArgs::parsedArgs()->isSet("loginhelper"); 89 | if (!is_login) { 90 | findLoginWindow(); 91 | } 92 | 93 | KvkbdApp app(is_login); 94 | 95 | return app.exec(); 96 | 97 | } 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 0.7 2 | * Polish KDE4 porting 3 | * Implement themese 4 | * Code cleanups 5 | 6 | 0.6 7 | * Fix behaviour of the caps lock, num lock, alt gr and shift keys(thanks to Scott for his Caps Lock patch!) 8 | * Repeating keys by pressing a button for a long amount of time now works correctly 9 | * Correctly save the configuration options 10 | * Remember if the extent was visible when closing and display it at the next start if it's the case 11 | * Added semantic markup to the i18n() calls 12 | * Added a hack so that keys "^" and "¨" are displayed correcly, at least on azerty keyboards 13 | * Correctly displays the "&" key(previously it only worked if it was accessible using the Shift key) 14 | * The numpad doesn't go beyond the screen edge when enabled near the right of the screen 15 | * Added a DBUS Interface 16 | * Use kdelibs coding style 17 | * Bug fixes and code cleanup 18 | * 0.5.99 regressions fixed: 19 | - The dock now show/hide the widget only when it is clicked, not dragged 20 | - Memleaks fixes (thanks to Laurent Montel!) 21 | - Update the keyboard mapping if xmodmap/setxkbmap changes it 22 | 23 | 0.5.99(only released for Kubuntu Intrepid Alpha) 24 | * KDE4 port 25 | * Use a double arrow icon instead of ">>" for the button to show/hide the numpad 26 | * Display a 4 arrows cursor when dragging the keyboard 27 | * Various bug fixes and code cleanup 28 | * User manual for Kvkbd 29 | 30 | 0.5 31 | * added lock function in settings menu to make app window stay locked on the screen. 32 | * right button clicking behave as if shift is clicked. 33 | 34 | 0.4.9 35 | * new dcop commands docw_show, docw_hide, docw_state query and toggle the dockwidget state 36 | 37 | 0.4.8 38 | * dcop scripting fixes, now implements show, hide and state functions. Usage 'dcop kvkbd kvkbd' to see all functions. 'dcop kvkbd kvkbd "show()"' to show the widget explicitly. 39 | * Fix to correctly save and restore the visibility state of the keyboard widget. 40 | 41 | 0.4.7 42 | * new button to popup the dockmenu, helping users without right click. 43 | * Store/Restore position of the keyboard on screen. 44 | 45 | 0.4.6 46 | * bugfix when started without x running. Confirm working with KDM and --loginhelper option passed (tested in kubuntu) 47 | 48 | 0.4.5 49 | * Auto font size implemented 50 | * Button repeating function. 51 | 52 | 0.4 53 | * Resizable/Moveable main window. Numeric/Cursor pad layer. Additional dcop command - toggle 54 | 55 | 0.3.1 56 | * dcop commands added: 57 | - use dcop kvkbd kvkbd show and dcop kvkbd kvkbd hide to toggle visibilty 58 | 59 | 0.3 60 | * First run syncing with current choosen keyboard layout 61 | * Font configuration implemented 62 | * "-loginhelper" option to be used on KDM/XDM screen (an entry should be added in Xsetup if you want kvkbd on the login screen - kvkbd -loginhelper -display :0) 63 | * Caps/Shift mode updates for non latin keyboards. 64 | * Systray left mouse button update as requested 65 | 66 | 0.2 67 | * characters on the virtual keyboard are now changed to the right characters when the localization of the keyboard (e.g. US->CZ) is changed. 68 | * Dock widget tolerant to pen press 69 | 70 | 0.1 71 | * Initial version 72 | -------------------------------------------------------------------------------- /src/vbutton.cpp: -------------------------------------------------------------------------------- 1 | #include "vbutton.h" 2 | #include 3 | 4 | #define TIMER_INTERVAL_SHORT 40 5 | #define TIMER_INTERVAL_LONG 200 6 | 7 | int VButton::RepeatShortDelay = TIMER_INTERVAL_SHORT; 8 | int VButton::RepeatLongDelay = TIMER_INTERVAL_LONG; 9 | 10 | 11 | VButton::VButton(QWidget *parent) : 12 | QPushButton(parent) 13 | { 14 | 15 | setFocusPolicy(Qt::NoFocus); 16 | setAttribute(Qt::WA_AlwaysShowToolTips); 17 | 18 | keyCode = 0; 19 | 20 | rightClicked = false; 21 | mTextIndex = 0; 22 | isCaps = false; 23 | 24 | keyTimer = new QTimer(this); 25 | 26 | connect(keyTimer, SIGNAL(timeout()), this, SLOT(repeatKey())); 27 | 28 | } 29 | 30 | void VButton::storeSize() 31 | { 32 | vpos = geometry(); 33 | 34 | } 35 | 36 | QRect VButton::VRect() 37 | { 38 | return vpos; 39 | 40 | } 41 | 42 | void VButton::setKeyCode(unsigned int keyCode) 43 | { 44 | this->keyCode = keyCode; 45 | } 46 | 47 | unsigned int VButton::getKeyCode() 48 | { 49 | return this->keyCode; 50 | 51 | } 52 | 53 | void VButton::setButtonText(const ButtonText& text) 54 | { 55 | this->mButtonText = text; 56 | } 57 | 58 | ButtonText VButton::buttonText() const 59 | { 60 | return this->mButtonText; 61 | } 62 | 63 | void VButton::setTextIndex(int index) 64 | { 65 | this->mTextIndex = index; 66 | } 67 | 68 | int VButton::textIndex() 69 | { 70 | return this->mTextIndex; 71 | 72 | } 73 | 74 | void VButton::nextText() 75 | { 76 | if (mButtonText.count()<1)return; 77 | 78 | mTextIndex++; 79 | int textCount = mButtonText.count()-1; 80 | if (mTextIndex>textCount) mTextIndex=0; 81 | 82 | 83 | updateText(); 84 | 85 | 86 | } 87 | 88 | void VButton::setCaps(bool mode) 89 | { 90 | if (mButtonText.count()<1)return; 91 | 92 | isCaps = mode; 93 | 94 | 95 | 96 | } 97 | void VButton::setShift(bool mode) 98 | { 99 | if (mButtonText.count()<1)return; 100 | if (mode) { 101 | this->mTextIndex = 1; 102 | } 103 | else { 104 | this->mTextIndex = 0; 105 | 106 | } 107 | isShift = mode; 108 | } 109 | void VButton::updateText() 110 | { 111 | if (mButtonText.count()<1)return; 112 | 113 | QString text = mButtonText.at(this->mTextIndex); 114 | if (text == "&") { 115 | text+="&"; 116 | } 117 | 118 | bool doCaps = isCaps ; 119 | if (isShift) doCaps = !doCaps; 120 | 121 | if (doCaps) { 122 | text = text.toUpper(); 123 | } 124 | else { 125 | text = text.toLower(); 126 | } 127 | 128 | this->setText(text); 129 | 130 | } 131 | 132 | void VButton::sendKey() 133 | { 134 | emit keyClick(this->keyCode); 135 | } 136 | 137 | void VButton::mousePressEvent(QMouseEvent *e) 138 | { 139 | 140 | rightClicked = false; 141 | if (e->button() == Qt::RightButton) { 142 | 143 | rightClicked = true; 144 | 145 | } 146 | QPushButton::mousePressEvent(e); 147 | 148 | if (this->keyCode>0) { 149 | sendKey(); 150 | 151 | if (!isCheckable()) { 152 | if (!keyTimer->isActive()) { 153 | //200 ms is a bit more that the time needed for a single click 154 | keyTimer->start(VButton::RepeatLongDelay); 155 | 156 | } 157 | 158 | } 159 | } 160 | } 161 | 162 | void VButton::mouseReleaseEvent(QMouseEvent *e) 163 | { 164 | 165 | if (keyTimer->isActive())keyTimer->stop(); 166 | QPushButton::mouseReleaseEvent(e); 167 | } 168 | 169 | void VButton::repeatKey() 170 | { 171 | //if the user is still pressing the button after 200 ms, we assume 172 | //he wants the key to be quickly repeated and we decrease the interval 173 | if (keyTimer->interval() == VButton::RepeatLongDelay) { 174 | //TODO: make this configurable? 175 | keyTimer->setInterval(VButton::RepeatShortDelay); 176 | } 177 | 178 | sendKey(); 179 | } 180 | -------------------------------------------------------------------------------- /src/mainwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwidget.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "vbutton.h" 7 | 8 | 9 | MainWidget::MainWidget(QWidget *parent) : QWidget(parent) 10 | { 11 | 12 | } 13 | 14 | void MainWidget::setBaseSize(int w, int h) 15 | { 16 | bsize.setWidth(w); 17 | bsize.setHeight(h); 18 | 19 | } 20 | void MainWidget::updateGroupState(const ModifierGroupStateMap& stateMap) 21 | { 22 | QObjectList buttons = this->children(); 23 | ModifierGroupStateMapIterator itr(stateMap); 24 | QList text; 25 | 26 | while (itr.hasNext()) { 27 | itr.next(); 28 | QString group_name = itr.key(); 29 | bool state = itr.value(); 30 | 31 | for (int a=0; aproperty("group_toggle").toString(); 36 | QString btn_group_name = btn->property("group_name").toString(); 37 | QString group_label = btn->property("group_label").toString(); 38 | QString label = btn->property("label").toString(); 39 | 40 | if (QString::compare(group_toggle,group_name)==0) { 41 | 42 | if (group_label.length()>0 && label.length()>0) { 43 | if (state) { 44 | btn->setText(group_label); 45 | } 46 | else { 47 | btn->setText(label); 48 | } 49 | } 50 | 51 | } 52 | else if (QString::compare(group_name,"capslock")==0) { 53 | 54 | btn->setCaps(state); 55 | btn->updateText(); 56 | } 57 | 58 | if (QString::compare(btn_group_name, group_name)==0) { 59 | btn->setChecked(state); 60 | } 61 | 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | void MainWidget::textSwitch(bool setShift) 69 | { 70 | QObjectList buttons = this->children(); 71 | 72 | for (int a=0; asetShift(setShift); 77 | btn->updateText(); 78 | } 79 | 80 | } 81 | void MainWidget::updateLayout(int index, QString layout_name) 82 | { 83 | QObjectList buttons = this->children(); 84 | 85 | VKeyboard *vkbd = (VKeyboard*)QObject::sender(); 86 | 87 | for (int a=0; aproperty("label").toString().length()<1) { 92 | ButtonText text; 93 | 94 | vkbd->textForKeyCode(btn->getKeyCode(), text); 95 | btn->setButtonText(text); 96 | btn->updateText(); 97 | 98 | } 99 | 100 | if (btn->objectName()=="currentLayout") { 101 | btn->setText(layout_name); 102 | } 103 | } 104 | 105 | } 106 | 107 | 108 | void MainWidget::resizeEvent(QResizeEvent *ev) 109 | { 110 | 111 | const QSize& size = ev->size(); 112 | 113 | double dw = (double)size.width() / (double)bsize.width(); 114 | double dh = (double)size.height() / (double)bsize.height(); 115 | 116 | QObjectList buttons = this->children(); 117 | for (int a=0; aVRect(); 121 | 122 | btn->setGeometry((geom.x() * dw), (geom.y() * dh), (geom.width() * dw), (geom.height() * dh)); 123 | 124 | } 125 | 126 | updateFont(this->parentWidget()->font()); 127 | 128 | } 129 | 130 | void MainWidget::updateFont(const QFont& widgetFont) 131 | { 132 | 133 | int fontSize = widgetFont.pointSize(); 134 | if ( parentWidget()->property("autoresfont").toBool() ) { 135 | fontSize = (8.0 / 500.0) * this->parentWidget()->size().width(); 136 | } 137 | QString buttonStyle = QString("VButton { font-family:'%1'; font-size: %2px; font-weight:%3; font-style: %4; }").arg(widgetFont.family()).arg(fontSize).arg(widgetFont.bold() ? "bold" : "normal").arg(widgetFont.italic() ? "italic" : "normal"); 138 | this->setStyleSheet(buttonStyle); 139 | 140 | } 141 | #include "mainwidget.moc" 142 | -------------------------------------------------------------------------------- /doc/index.docbook: -------------------------------------------------------------------------------- 1 | 2 | Kvkbd"> 4 | 5 | 6 | 7 | 8 | ]> 9 | 10 | 11 | 12 | 13 | The &kvkbd; Handbook 14 | 15 | 16 | 17 | TodorGyumyushevyodor1@gmail.com 18 | 19 | 20 | GuillaumeMartressmarter@ubuntu.com 21 | 22 | 23 | 24 | 25 | 26 | 2007-2014 27 | Todor Gyumyushev 28 | 29 | 30 | 2008 31 | Guillaume Martres 32 | 33 | 34 | &FDLNotice; 35 | 36 | 2014-04-10 37 | 0.7.1 38 | 39 | 40 | 41 | &kvkbd; is a virtual keyboard for &kde; 42 | 43 | 44 | 45 | 46 | KDE 47 | Kvkbd 48 | keyboard 49 | virtual 50 | accessibility 51 | 52 | 53 | 54 | 55 | 56 | Introduction 57 | 58 | 59 | &kvkbd; is a simple virtual keyboard for &kde;. It can be used by disabled people who have trouble using a keyboard or for devices with a touch screen but no keyboard. 60 | It is also useful to quickly test a keyboard mapping to locate some keys. 61 | 62 | 63 | 64 | 65 | Using &kvkbd; 66 | 67 | &kvkbd; interface 68 | 69 | When first launched, &kvkbd; will appears in the bottom-right corner. You can move it by clicking on empty area and drag it anywhere on the screen. 70 | You can resize it by clicking on the stripes at the bottom-right. The button on the top right is used to hide the keyboard, if you want to show it again, just click on the tray icon. 71 | If you want to use the numeric keypad, press the green arrow on the right. 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | The configuration menu 80 | 81 | 82 | &kvkbd; configuration menu is accessible ever by clicking on the configuration button or by right-clicking on the tray icon. 83 | You can change the font used to display the keys by clicking on "Choose Font...". If you check "Auto Resize Font", the font will grow or shrink when &kvkbd; is resized. 84 | If you click on "Dock Keyboard", a small dock will appears. You can click on it to hide or show the virtual keyboard, you can also drag it anywhere on your screen. 85 | Finally, the "Lock on Screen" option will prevent the virtual keyboard from being dragged or resized. 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Using &kvkbd; with a display manager 95 | 96 | 97 | &kvkbd; can be used on a display manager, like KDM or XDM, to do this edit one of the following file: 98 | 99 | 100 | /etc/kde4/kdm/Xsetup for KDM/KDE4 101 | 102 | 103 | /etc/kde3/kdm/Xsetup for KDM/KDE3 104 | 105 | 106 | /etc/X11/xdm/Xsetup for XDM 107 | 108 | 109 | And add this at the end: 110 | 111 | HOME=/root kvkbd --loginhelper 112 | 113 | If you want to quit &kvkbd; once the session is started(useful to let the user launch his own instance of &kvkbd; with his own settings) edit: 114 | 115 | 116 | /etc/kde4/kdm/Xstartup for KDM/KDE4 117 | 118 | 119 | /etc/kde3/kdm/Xstartup for KDM/KDE3 120 | 121 | 122 | /etc/X11/xdm/Xstartup for XDM 123 | 124 | 125 | make a new line after the first line and add this to it: 126 | 127 | qdbus org.kde.kvkbd /MainApplication quit 128 | 129 | There is no configuration button in the loginhelper mode. If you want to change the default config, you can launch &kvkbd; as root using: 130 | 131 | $(kde4-config --path libexec)/kdesu kvkbd 132 | 133 | and make the changes here. 134 | You can also launches Kvkbd without the --loginhelper option, this is useful if you want to let the users of the system change the options of &kvkbd; 135 | and be able to minimize it in the systray without launching their own instance of it. 136 | 137 | 138 | 139 | 140 | 141 | 142 | Credits and License 143 | 144 | 145 | &kvkbd; 146 | 147 | 148 | Program Copyright © 2007-2014 Todor Gyumyushev yodor1@gmail.com 149 | 150 | 151 | Program and Documentation Copyright © 2008 Guillaume Martres smarter@ubuntu.com 152 | 153 | 154 | 155 | 156 | &underFDL; 157 | 158 | 163 | 164 | &underGPL; 165 | 166 | 167 | 168 | 169 | Installation 170 | 171 | 172 | Compilation and Installation 173 | 174 | 175 | 176 | 177 | 178 | &install.compile.documentation; 179 | 180 | 181 | 182 | 183 | &documentation.index; 184 | 185 | 186 | 198 | -------------------------------------------------------------------------------- /src/x11keyboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor Gyumyushev 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #include "x11keyboard.h" 21 | 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | #include "vbutton.h" 42 | extern QList modKeys; 43 | 44 | #include 45 | using namespace std; 46 | 47 | X11Keyboard::X11Keyboard(QObject *parent): VKeyboard(parent) 48 | { 49 | 50 | 51 | 52 | QString service = ""; 53 | QString path = "/Layouts"; 54 | QString interface = "org.kde.KeyboardLayouts"; 55 | 56 | QDBusConnection session = QDBusConnection::sessionBus(); 57 | 58 | session.connect(service, path, interface, "currentLayoutChanged", this, SLOT(layoutChanged())); 59 | session.connect(service, path, interface, "layoutListChanged", this, SLOT(constructLayouts())); 60 | 61 | constructLayouts(); 62 | groupTimer = new QTimer(parent); 63 | groupTimer->setInterval(250); 64 | 65 | 66 | groupState.insert("capslock", this->queryModKeyState(XK_Caps_Lock)); 67 | groupState.insert("numlock", this->queryModKeyState(XK_Num_Lock)); 68 | 69 | connect(groupTimer, SIGNAL(timeout()), this, SLOT(queryModState())); 70 | 71 | 72 | 73 | } 74 | 75 | X11Keyboard::~X11Keyboard() 76 | { 77 | 78 | } 79 | 80 | void X11Keyboard::start() 81 | { 82 | layoutChanged(); 83 | emit groupStateChanged(groupState); 84 | groupTimer->start(); 85 | } 86 | 87 | void X11Keyboard::constructLayouts() 88 | { 89 | QDBusInterface iface("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts", QDBusConnection::sessionBus()); 90 | 91 | QDBusReply reply = iface.call("getLayoutsList"); 92 | if (reply.isValid()) { 93 | 94 | QStringList lst = reply.value(); 95 | layouts.clear(); 96 | 97 | QListIterator itr(lst); 98 | 99 | while (itr.hasNext()) { 100 | QString layout_name = itr.next(); 101 | layouts << layout_name; 102 | } 103 | 104 | } 105 | 106 | } 107 | 108 | void X11Keyboard::processKeyPress(unsigned int keyCode) 109 | { 110 | groupTimer->stop(); 111 | sendKey(keyCode); 112 | emit keyProcessComplete(keyCode); 113 | groupTimer->start(); 114 | 115 | } 116 | void X11Keyboard::sendKey(unsigned int keycode) 117 | { 118 | Window currentFocus; 119 | int revertTo; 120 | 121 | Display *display = QX11Info::display(); 122 | XGetInputFocus(display, ¤tFocus, &revertTo); 123 | 124 | QListIterator itr(modKeys); 125 | while (itr.hasNext()) { 126 | VButton *mod = itr.next(); 127 | if (mod->isChecked()) { 128 | XTestFakeKeyEvent(display, mod->getKeyCode(), true, 2); 129 | } 130 | } 131 | 132 | XTestFakeKeyEvent(display, keycode, true, 2); 133 | XTestFakeKeyEvent(display, keycode, false, 2); 134 | 135 | itr.toFront(); 136 | while (itr.hasNext()) { 137 | VButton *mod = itr.next(); 138 | if (mod->isChecked()) { 139 | XTestFakeKeyEvent(display, mod->getKeyCode(), false, 2); 140 | } 141 | } 142 | 143 | 144 | XFlush(display); 145 | 146 | } 147 | 148 | bool X11Keyboard::queryModKeyState(KeySym iKey) 149 | { 150 | int iKeyMask = 0; 151 | Window wDummy1, wDummy2; 152 | int iDummy3, iDummy4, iDummy5, iDummy6; 153 | unsigned int iMask; 154 | 155 | Display* display = QX11Info::display(); 156 | 157 | XModifierKeymap* map = XGetModifierMapping(display); 158 | KeyCode keyCode = XKeysymToKeycode(display, iKey); 159 | if (keyCode == NoSymbol) return false; 160 | for (int i = 0; i < 8; ++i) { 161 | if (map->modifiermap[map->max_keypermod * i] == keyCode) { 162 | iKeyMask = 1 << i; 163 | } 164 | } 165 | XQueryPointer(display, DefaultRootWindow(display), &wDummy1, &wDummy2, &iDummy3, &iDummy4, &iDummy5, &iDummy6, &iMask); 166 | XFreeModifiermap(map); 167 | return ((iMask & iKeyMask) != 0); 168 | } 169 | 170 | void X11Keyboard::queryModState() 171 | { 172 | 173 | bool curr_caps_state = this->queryModKeyState(XK_Caps_Lock); 174 | bool curr_num_state = this->queryModKeyState(XK_Num_Lock); 175 | 176 | bool caps_state = groupState.value("capslock"); 177 | bool num_state = groupState.value("numlock"); 178 | 179 | groupState.insert("capslock", curr_caps_state); 180 | groupState.insert("numlock", curr_num_state); 181 | 182 | if (curr_caps_state != caps_state || curr_num_state != num_state) { 183 | 184 | emit groupStateChanged(groupState); 185 | } 186 | 187 | } 188 | 189 | 190 | void X11Keyboard::layoutChanged() 191 | { 192 | 193 | //std::cerr << "LayoutChanged" << std::endl; 194 | 195 | QDBusInterface iface("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts", QDBusConnection::sessionBus()); 196 | 197 | QDBusReply reply = iface.call("getCurrentLayout"); 198 | 199 | if (reply.isValid()) { 200 | 201 | QString current_layout = reply.value(); 202 | 203 | layout_index = layouts.indexOf(current_layout); 204 | 205 | emit layoutUpdated(layout_index, layouts.at(layout_index)); 206 | } 207 | else { 208 | layout_index = 0; 209 | 210 | emit layoutUpdated(0, "us"); 211 | } 212 | 213 | } 214 | void X11Keyboard::textForKeyCode(unsigned int keyCode, ButtonText& text) 215 | { 216 | if (keyCode==0) { 217 | text.clear(); 218 | return; 219 | } 220 | 221 | KeyCode button_code = keyCode; 222 | 223 | int keysyms_per_keycode = 0; 224 | 225 | KeySym *keysym = XGetKeyboardMapping (QX11Info::display(), button_code, 1, &keysyms_per_keycode); 226 | 227 | int index_normal = layout_index * 2; 228 | int index_shift = index_normal + 1; 229 | 230 | KeySym normal = keysym[index_normal]; 231 | KeySym shift = keysym[index_shift]; 232 | 233 | 234 | long int ret = kconvert.convert(normal); 235 | long int shiftRet = kconvert.convert(shift); 236 | 237 | QChar normalText = QChar((uint)ret); 238 | QChar shiftText = QChar((uint)shiftRet); 239 | 240 | //cout << "Normal Text " << normalText.toAscii() << " Shift Text: " << shiftText.toAscii() << std::endl; 241 | 242 | text.clear(); 243 | text.append(normalText); 244 | text.append(shiftText); 245 | 246 | XFree ((char *) keysym); 247 | 248 | } 249 | 250 | 251 | -------------------------------------------------------------------------------- /themes/standart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /src/standart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /src/kvkbdapp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Kvkbd project. 3 | * Copyright (C) 2007-2014 Todor Gyumyushev 4 | * Copyright (C) 2008 Guillaume Martres 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "kvkbdapp.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | 44 | #include 45 | #include 46 | 47 | #include 48 | 49 | 50 | 51 | QList modKeys; 52 | 53 | #include 54 | using namespace std; 55 | 56 | #define DEFAULT_WIDTH 640 57 | #define DEFAULT_HEIGHT 210 58 | 59 | #include "x11keyboard.h" 60 | 61 | 62 | KvkbdApp::KvkbdApp(bool loginhelper) : KUniqueApplication(), is_login(loginhelper) 63 | // : KApplication() 64 | { 65 | 66 | signalMapper = new QSignalMapper(this); 67 | connect(signalMapper, SIGNAL(mapped(const QString &)), this, SLOT(buttonAction(const QString &))); 68 | 69 | widget = new ResizableDragWidget(0); 70 | widget->setContentsMargins(10,10,10,10); 71 | widget->setProperty("name", "main"); 72 | 73 | KConfigGroup cfg = KGlobal::config()->group(""); 74 | 75 | 76 | 77 | if (!is_login) { 78 | widget->setAttribute(Qt::WA_ShowWithoutActivating); 79 | widget->setAttribute(Qt::WA_DeleteOnClose, false); 80 | } 81 | 82 | widget->setWindowFlags( Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint ); 83 | 84 | dock = new KbdDock(widget->winId()); 85 | connect(dock, SIGNAL(requestVisibility()), widget, SLOT(toggleVisibility())); 86 | 87 | tray = new KbdTray(widget); 88 | connect(tray, SIGNAL(requestVisibility()), widget, SLOT(toggleVisibility())); 89 | 90 | 91 | layout = new QGridLayout(widget); 92 | layout->setContentsMargins(0,0,0,0); 93 | widget->setLayout(layout); 94 | 95 | 96 | xkbd = new X11Keyboard(this); 97 | 98 | 99 | themeLoader = new ThemeLoader(widget); 100 | 101 | 102 | connect(themeLoader, SIGNAL(partLoaded(MainWidget*, int, int)), this, SLOT(partLoaded(MainWidget*, int, int))); 103 | connect(themeLoader, SIGNAL(buttonLoaded(VButton*)), this, SLOT(buttonLoaded(VButton*))); 104 | 105 | 106 | 107 | 108 | QMenu *cmenu = tray->contextMenu(); 109 | 110 | KAction *chooseFontAction = new KAction(KIcon("preferences-desktop-font"), i18nc("@action:inmenu", "Choose Font..."), this); 111 | connect(chooseFontAction, SIGNAL(triggered(bool)), this, SLOT(chooseFont()) ); 112 | cmenu->addAction(chooseFontAction); 113 | 114 | KToggleAction *autoResizeAction = new KToggleAction(i18nc("@action:inmenu", "Auto Resize Font"), this); 115 | bool autoResizeEnabled = cfg.readEntry("autoresfont",true); 116 | autoResizeAction->setChecked(autoResizeEnabled); 117 | widget->setProperty("autoresfont", autoResizeEnabled); 118 | cmenu->addAction(autoResizeAction); 119 | connect(autoResizeAction,SIGNAL(triggered(bool)), this, SLOT(autoResizeFont(bool))); 120 | 121 | 122 | bool blur = cfg.readEntry("blurBackground", QVariant(true)).toBool(); 123 | 124 | KToggleAction *blurBackgroundAction = new KToggleAction(i18nc("@action:inmenu", "Blur Background"), this); 125 | blurBackgroundAction->setChecked(blur); 126 | cmenu->addAction(blurBackgroundAction); 127 | widget->blurBackground(blur); 128 | connect(blurBackgroundAction,SIGNAL(triggered(bool)), widget, SLOT(blurBackground(bool))); 129 | dock->blurBackground(blur); 130 | connect(blurBackgroundAction,SIGNAL(triggered(bool)), dock, SLOT(blurBackground(bool))); 131 | widget->blurBackground(blur); 132 | dock->blurBackground(blur); 133 | 134 | bool dockVisible = cfg.readEntry("showdock", QVariant(false)).toBool(); 135 | KToggleAction *showDockAction = new KToggleAction(i18nc("@action:inmenu", "Show Dock"), this); 136 | showDockAction->setChecked(dockVisible); 137 | cmenu->addAction(showDockAction); 138 | connect(showDockAction,SIGNAL(triggered(bool)), dock, SLOT(setVisible(bool))); 139 | 140 | bool isLocked = cfg.readEntry("locked", QVariant(false)).toBool(); 141 | KToggleAction *lockOnScreenAction = new KToggleAction(i18nc("@action:inmenu", "Lock on Screen"), this); 142 | lockOnScreenAction->setChecked(isLocked); 143 | cmenu->addAction(lockOnScreenAction); 144 | connect(lockOnScreenAction,SIGNAL(triggered(bool)), widget, SLOT(setLocked(bool))); 145 | 146 | bool stickyModKeys = cfg.readEntry("stickyModKeys", QVariant(false)).toBool(); 147 | KToggleAction *stickyModKeysAction = new KToggleAction(i18nc("@action:inmenu", "Sticky Modifier Keys"), this); 148 | stickyModKeysAction->setChecked(stickyModKeys); 149 | cmenu->addAction(stickyModKeysAction); 150 | connect(stickyModKeysAction,SIGNAL(triggered(bool)), this, SLOT(setStickyModKeys(bool))); 151 | widget->setProperty("stickyModKeys", stickyModKeys); 152 | 153 | 154 | QFont font = cfg.readEntry("font", widget->font()); 155 | widget->setFont(font); 156 | 157 | QString colorsFilename = cfg.readEntry("colors"); 158 | QMenu *colors = new QMenu(widget); 159 | themeLoader->findColorStyles(colors, colorsFilename); 160 | cmenu->addMenu(colors); 161 | connect(themeLoader, SIGNAL(colorStyleChanged()), widget, SLOT(repaint())); 162 | connect(themeLoader, SIGNAL(colorStyleChanged()), dock, SLOT(repaint())); 163 | 164 | KHelpMenu *helpMenu = new KHelpMenu(widget, KCmdLineArgs::aboutData()); 165 | cmenu->addMenu((QMenu*)helpMenu->menu()); 166 | 167 | QString themeName = cfg.readEntry("layout", "standart"); 168 | themeLoader->loadTheme(themeName); 169 | widget->setProperty("layout", themeName); 170 | 171 | 172 | QSize defaultSize(DEFAULT_WIDTH,DEFAULT_HEIGHT); 173 | QDesktopWidget *pDesktop = QApplication::desktop(); 174 | 175 | QRect screenGeometry = pDesktop->availableGeometry(pDesktop->underMouse()); 176 | qDebug() << "ScreenGeometry: " << screenGeometry; 177 | 178 | QPoint bottomRight = screenGeometry.bottomRight()-QPoint(defaultSize.width(), defaultSize.height()); 179 | 180 | QRect widgetGeometry(bottomRight, defaultSize); 181 | qDebug() << "widgetGeometry: " << widgetGeometry; 182 | 183 | QRect c_geometry = cfg.readEntry("geometry", widgetGeometry); 184 | if (!screenGeometry.contains(c_geometry, true)) { 185 | c_geometry = widgetGeometry; 186 | } 187 | widget->setGeometry(c_geometry); 188 | 189 | QPoint pos = c_geometry.topLeft(); 190 | pos.setY(pos.y()-dock->height()); 191 | 192 | QRect dockGeometry(pos, dock->size()); 193 | 194 | QRect c_dock_geometry = cfg.readEntry("dockGeometry", dockGeometry); 195 | if (!screenGeometry.contains(c_dock_geometry, true)) { 196 | c_dock_geometry = dockGeometry; 197 | } 198 | dock->setGeometry(c_dock_geometry); 199 | 200 | widget->show(); 201 | 202 | 203 | bool extensionVisible = cfg.readEntry("extentVisible", QVariant(true)).toBool(); 204 | if (!extensionVisible) { 205 | toggleExtension(); 206 | } 207 | 208 | 209 | 210 | setQuitOnLastWindowClosed (is_login); 211 | 212 | connect(this, SIGNAL(aboutToQuit()), this, SLOT(storeConfig())); 213 | emit fontUpdated(widget->font()); 214 | 215 | if (dockVisible && !is_login) { 216 | dock->show(); 217 | } 218 | 219 | xkbd->start(); 220 | 221 | if (!is_login) { 222 | bool vis = cfg.readEntry("visible", QVariant(true)).toBool(); 223 | if (!vis ) { 224 | 225 | widget->showMinimized(); 226 | 227 | } 228 | widget->setWindowTitle("kvkbd"); 229 | tray->show(); 230 | } 231 | else { 232 | QTimer *timer = new QTimer(this); 233 | timer->setInterval(1000); 234 | connect(timer, SIGNAL(timeout()), widget, SLOT(raise())); 235 | timer->start(); 236 | widget->setWindowTitle("kvkbd.login"); 237 | } 238 | 239 | } 240 | 241 | KvkbdApp::~KvkbdApp() 242 | { 243 | 244 | } 245 | 246 | void KvkbdApp::storeConfig() 247 | { 248 | KConfigGroup cfg = KGlobal::config()->group(""); 249 | 250 | cfg.writeEntry("visible", widget->isVisible()); 251 | cfg.writeEntry("geometry", widget->geometry()); 252 | cfg.writeEntry("locked", widget->isLocked()); 253 | cfg.writeEntry("stickyModKeys", widget->property("stickyModKeys")); 254 | 255 | cfg.writeEntry("showdock", dock->isVisible()); 256 | cfg.writeEntry("dockGeometry", dock->geometry()); 257 | 258 | cfg.writeEntry("layout", widget->property("layout")); 259 | cfg.writeEntry("colors", widget->property("colors")); 260 | cfg.writeEntry("font", widget->font()); 261 | cfg.writeEntry("autoresfont", widget->property("autoresfont").toBool()); 262 | cfg.writeEntry("blurBackground", widget->property("blurBackground").toBool()); 263 | 264 | MainWidget *prt = parts.value("extension"); 265 | if (prt) { 266 | cfg.writeEntry("extentVisible", prt->isVisible()); 267 | } 268 | 269 | cfg.sync(); 270 | 271 | } 272 | 273 | 274 | void KvkbdApp::autoResizeFont(bool mode) 275 | { 276 | widget->setProperty("autoresfont", QVariant(mode)); 277 | emit fontUpdated(widget->font()); 278 | 279 | } 280 | void KvkbdApp::setStickyModKeys(bool mode) 281 | { 282 | widget->setProperty("stickyModKeys", QVariant(mode)); 283 | } 284 | 285 | void KvkbdApp::chooseFont() 286 | { 287 | bool restore = false; 288 | 289 | if (widget->isVisible()) { 290 | widget->hide(); 291 | restore = true; 292 | } 293 | 294 | QFont widgetFont = widget->font(); 295 | 296 | int result = KFontDialog::getFont( widgetFont, KFontChooser::NoDisplayFlags, widget ); 297 | if ( result == KFontDialog::Accepted ) { 298 | 299 | widget->setFont(widgetFont); 300 | emit fontUpdated(widgetFont); 301 | 302 | } 303 | 304 | if (restore) { 305 | widget->show(); 306 | } 307 | 308 | 309 | } 310 | 311 | 312 | 313 | 314 | void KvkbdApp::buttonLoaded(VButton *btn) 315 | { 316 | if (btn->property("modifier").toBool() == true) { 317 | modKeys.append(btn); 318 | } 319 | else { 320 | QObject::connect(btn, SIGNAL(keyClick(unsigned int)), xkbd, SLOT(processKeyPress(unsigned int)) ); 321 | } 322 | QString bAction = btn->property("action").toString(); 323 | 324 | if (bAction.length()>0) { 325 | connect(btn, SIGNAL(clicked()), signalMapper, SLOT(map())); 326 | signalMapper->setMapping(btn, bAction); 327 | actionButtons.insertMulti(bAction, btn); 328 | } 329 | 330 | QString tooltip = btn->property("tooltip").toString(); 331 | if (tooltip.length()>0) { 332 | btn->setToolTip(tooltip); 333 | 334 | } 335 | 336 | } 337 | void KvkbdApp::partLoaded(MainWidget *vPart, int total_rows, int total_cols) 338 | { 339 | //cout << "Col Strech: " << total_cols << endl; 340 | // cout << "Row Strech: " << total_rows << endl; 341 | 342 | QString partName = vPart->property("part").toString(); 343 | 344 | int row_pos = 0; 345 | int col_pos = 0; 346 | 347 | if (layoutPosition.count()>0) { 348 | QString partName = layoutPosition.keys().at(0); 349 | QRect lp = layoutPosition.value(partName); 350 | col_pos = lp.width(); 351 | } 352 | 353 | layout->addWidget(vPart,row_pos,col_pos,total_rows,total_cols); 354 | //cout << "Insert to layout: " << qPrintable(partName) << " RowStart: " << row_pos << " ColStart: " << col_pos << " RowSpan: " << total_rows << " ColSpan: " << total_cols << endl; 355 | parts.insert(partName, vPart); 356 | layoutPosition.insert(partName, QRect(col_pos,row_pos,total_cols,total_rows)); 357 | 358 | QObject::connect(xkbd, SIGNAL(layoutUpdated(int,QString)), vPart, SLOT(updateLayout(int,QString))); 359 | QObject::connect(xkbd, SIGNAL(groupStateChanged(const ModifierGroupStateMap&)), vPart, SLOT(updateGroupState(const ModifierGroupStateMap&))); 360 | QObject::connect(xkbd, SIGNAL(keyProcessComplete(unsigned int)), this, SLOT(keyProcessComplete(unsigned int))); 361 | 362 | QObject::connect(this, SIGNAL(textSwitch(bool)), vPart, SLOT(textSwitch(bool))); 363 | QObject::connect(this, SIGNAL(fontUpdated(const QFont&)), vPart, SLOT(updateFont(const QFont&))); 364 | 365 | 366 | 367 | } 368 | void KvkbdApp::keyProcessComplete(unsigned int) 369 | { 370 | if (widget->property("stickyModKeys").toBool()) return; 371 | 372 | QListIterator itr(modKeys); 373 | while (itr.hasNext()) { 374 | VButton *mod = itr.next(); 375 | if (mod->isChecked()) { 376 | mod->click(); 377 | } 378 | } 379 | } 380 | 381 | void KvkbdApp::buttonAction(const QString &action) 382 | { 383 | 384 | if (QString::compare(action , "toggleVisibility")==0) { 385 | if (!is_login) { 386 | widget->toggleVisibility(); 387 | } 388 | } 389 | else if (QString::compare(action , "toggleExtension")==0) { 390 | 391 | toggleExtension(); 392 | } 393 | else if (QString::compare(action, "shiftText")==0) { 394 | if (actionButtons.contains(action)) { 395 | QList buttons = actionButtons.values(action); 396 | QListIterator itr(buttons); 397 | bool setShift = false; 398 | while (itr.hasNext()) { 399 | VButton *btn = itr.next(); 400 | if (btn->isCheckable() && btn->isChecked()) setShift=true; 401 | } 402 | emit textSwitch(setShift); 403 | } 404 | } 405 | } 406 | void KvkbdApp::toggleExtension() 407 | { 408 | MainWidget *prt = parts.value("extension"); 409 | if (prt->isVisible()) { 410 | prt->hide(); 411 | layout->removeWidget(prt); 412 | } 413 | else { 414 | QString partName = prt->property("part").toString(); 415 | QRect span = layoutPosition.value(partName); 416 | layout->addWidget(prt,span.y(),span.x(), span.height(), span.width()); 417 | prt->show(); 418 | } 419 | } 420 | 421 | 422 | 423 | 424 | #include "kvkbdapp.moc" 425 | -------------------------------------------------------------------------------- /src/themeloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) 2014 Todor 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #include "themeloader.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | #include 40 | using namespace std; 41 | 42 | 43 | int defaultWidth = 25; 44 | int defaultHeight = 25; 45 | 46 | #define DEFAULT_CSS ":/theme/standart.css" 47 | 48 | ThemeLoader::ThemeLoader(QWidget *parent) : QObject(parent) 49 | { 50 | 51 | } 52 | 53 | ThemeLoader::~ThemeLoader() 54 | { 55 | 56 | } 57 | void ThemeLoader::loadTheme(QString& themeName) 58 | { 59 | bool loading = true; 60 | while (loading) { 61 | int ret = this->loadLayout(themeName, ":/theme/"); 62 | 63 | if (ret == 0) { 64 | break; 65 | } 66 | //bail out 67 | else { 68 | if (QString::compare(themeName, "standart")==0) { 69 | loading = false; 70 | kapp->quit(); 71 | } 72 | else { 73 | themeName="standart"; 74 | } 75 | } 76 | } 77 | } 78 | void ThemeLoader::loadColorFile(const QString& fileName) 79 | { 80 | QFile themeFile; 81 | 82 | themeFile.setFileName(fileName); 83 | 84 | if (!themeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 85 | 86 | QMessageBox::information(0, "Error", QString("Unable to open css file: %1").arg(themeFile.fileName())); 87 | return; 88 | } 89 | 90 | ((QWidget*)parent())->setStyleSheet(themeFile.readAll()); 91 | ((QWidget*)parent())->setProperty("colors", fileName); 92 | themeFile.close(); 93 | 94 | ((QWidget*)parent())->repaint(); 95 | 96 | emit colorStyleChanged(); 97 | 98 | 99 | } 100 | void ThemeLoader::loadColorStyle() 101 | { 102 | 103 | QAction *action = (QAction*)QObject::sender(); 104 | 105 | QFileInfo info(action->data().toString()); 106 | 107 | this->loadColorFile(info.absoluteFilePath()); 108 | 109 | } 110 | void ThemeLoader::findColorStyles(QMenu *colors, const QString& configSelectedStyle) 111 | { 112 | KStandardDirs kdirs; 113 | QStringList dirs = kdirs.findDirs("data", "kvkbd"); 114 | 115 | QActionGroup *color_group = new QActionGroup(colors); 116 | color_group->setExclusive(true); 117 | 118 | 119 | QAction *item = new QAction(colors); 120 | item->setCheckable(true); 121 | item->setText("standart"); 122 | item->setData(":/theme/standart.css"); 123 | colors->addAction(item); 124 | color_group->addAction(item); 125 | 126 | 127 | 128 | 129 | 130 | colors->setTitle("Color Style"); 131 | colors->setIcon(KIcon("preferences-desktop-color")); 132 | QListIterator itr(dirs); 133 | while (itr.hasNext()) { 134 | QString data_path = itr.next() + "colors"; 135 | 136 | QFileInfo info(data_path); 137 | if (info.isDir() && info.isReadable()) { 138 | QDir colors_dir(info.absoluteFilePath(), "*.css"); 139 | QFileInfoList list = colors_dir.entryInfoList(); 140 | 141 | QListIterator itr(list); 142 | while (itr.hasNext()) { 143 | QFileInfo fileInfo = itr.next(); 144 | //std::cout << qPrintable(QString("%1 %2").arg(fileInfo.size(), 10) 145 | // .arg(fileInfo.fileName())); 146 | //std::cout << std::endl; 147 | 148 | QAction *item = new QAction(this); 149 | item->setCheckable(true); 150 | 151 | item->setText(fileInfo.baseName()); 152 | item->setData(fileInfo.absoluteFilePath()); 153 | colors->addAction(item); 154 | color_group->addAction(item); 155 | 156 | 157 | } 158 | 159 | } 160 | 161 | } 162 | 163 | QString selectedStyle = configSelectedStyle; 164 | if (selectedStyle.length()<1) { 165 | selectedStyle = DEFAULT_CSS; 166 | } 167 | QAction *selectedAction = 0; 168 | 169 | QListIterator itrActions(color_group->actions()); 170 | while (itrActions.hasNext()) { 171 | QAction *item = itrActions.next(); 172 | 173 | if (item->data().toString() == selectedStyle) { 174 | item->setChecked(true); 175 | selectedAction = item; 176 | } 177 | 178 | 179 | connect(item, SIGNAL(triggered(bool)), this, SLOT(loadColorStyle())); 180 | } 181 | 182 | if (selectedAction) { 183 | selectedAction->trigger(); 184 | } 185 | 186 | } 187 | 188 | 189 | int ThemeLoader::loadLayout(const QString& themeName, const QString& path) 190 | { 191 | 192 | // const KArchiveDirectory * KArchive::directory ( ) const 193 | 194 | 195 | QFile themeFile; 196 | 197 | 198 | 199 | QDomDocument doc; 200 | 201 | themeFile.setFileName(QString(path + "%1.xml").arg(themeName)); 202 | 203 | if (!themeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 204 | QMessageBox::information(0, "Error", QString("Unable to open theme xml file: %1").arg(themeFile.fileName())); 205 | return -1; 206 | } 207 | if (!doc.setContent(&themeFile)) { 208 | QMessageBox::information(0, "Error", QString("Unable to parse theme xml file: %1").arg(themeFile.fileName())); 209 | return -2; 210 | } 211 | themeFile.close(); 212 | 213 | 214 | QDomElement docElem = doc.documentElement(); 215 | 216 | QDomNodeList wList = docElem.elementsByTagName("buttonWidth"); 217 | QDomNode wNode = wList.at(0); 218 | 219 | //read default button width 220 | defaultWidth = wNode.attributes().namedItem("width").toAttr().value().toInt(); 221 | 222 | QDomNodeList nList = (wNode.toElement()).elementsByTagName("item"); 223 | for (int a=0; a"<< width << endl; 229 | } 230 | 231 | wList = docElem.elementsByTagName("buttonHeight"); 232 | wNode = wList.at(0); 233 | nList = (wNode.toElement()).elementsByTagName("item"); 234 | for (int a=0; a"<< height << endl; 240 | } 241 | 242 | 243 | wList = docElem.elementsByTagName("spacingHints"); 244 | wNode = wList.at(0); 245 | nList = (wNode.toElement()).elementsByTagName("item"); 246 | for (int a=0; a"<< width << endl; 252 | } 253 | 254 | 255 | wList = docElem.elementsByTagName("part"); 256 | wNode = wList.at(0); 257 | 258 | //insert main part to widget 259 | QString partName = wNode.attributes().namedItem("name").toAttr().value(); 260 | 261 | MainWidget *part = new MainWidget((QWidget*)parent()); 262 | part->setProperty("part", "main"); 263 | 264 | 265 | loadKeys(part, wNode); 266 | 267 | wList = wNode.childNodes(); 268 | 269 | for (int a=0; asetProperty("part", "extension"); 275 | loadKeys(widget1, wNode); 276 | break; 277 | } 278 | } 279 | 280 | 281 | 282 | return 0; 283 | } 284 | bool ThemeLoader::applyProperty(VButton *btn, const QString& attributeName, QDomNamedNodeMap *attributes, QVariant defaultValue) 285 | { 286 | bool ret = false; 287 | 288 | QString attributeValue = attributes->namedItem(attributeName).toAttr().value(); 289 | if (attributeValue.length()>0) { 290 | btn->setProperty(qPrintable(attributeName), attributeValue); 291 | ret = true; 292 | } 293 | else { 294 | if (defaultValue.toString().length()>0) { 295 | btn->setProperty(qPrintable(attributeName), defaultValue); 296 | ret = true; 297 | } 298 | } 299 | return ret; 300 | } 301 | void ThemeLoader::loadKeys(MainWidget *vPart, const QDomNode& wNode) 302 | { 303 | int max_sx = 0; 304 | int max_sy = 0; 305 | 306 | int sx = 0; 307 | int sy = 0; 308 | int rowMarginLeft = 0; 309 | int rowSpacingY = 0; 310 | int rowSpacingX = 0; 311 | 312 | int total_cols = 0; 313 | int total_rows = 0; 314 | 315 | QDomNodeList nList = wNode.childNodes(); 316 | 317 | //(wNode.toElement()).elementsByTagName("row"); 318 | 319 | for (int a=0; a0) { 365 | btn->setObjectName(button_name); 366 | } 367 | 368 | 369 | if (applyProperty(btn, "label", &attributes)) { 370 | btn->setText(btn->property("label").toString()); 371 | } 372 | 373 | 374 | applyProperty(btn, "group_label", &attributes); 375 | 376 | applyProperty(btn, "group_toggle", &attributes); 377 | 378 | applyProperty(btn, "group_name", &attributes); 379 | 380 | applyProperty(btn, "colorGroup", &attributes, "normal"); 381 | 382 | applyProperty(btn, "tooltip", &attributes); 383 | 384 | QString modifier = attributes.namedItem("modifier").toAttr().value(); 385 | if (modifier.toInt()>0) { 386 | btn->setProperty("modifier", true); 387 | btn->setCheckable(true); 388 | } 389 | 390 | unsigned int key_code = attributes.namedItem("code").toAttr().value().toInt(); 391 | if (key_code>0) { 392 | btn->setKeyCode(key_code); 393 | } 394 | 395 | if (applyProperty(btn, "action", &attributes)) { 396 | btn->setProperty("action", btn->property("action").toString()); 397 | 398 | } 399 | 400 | 401 | int is_checkable = attributes.namedItem("checkable").toAttr().value().toInt(); 402 | if (is_checkable>0) { 403 | btn->setCheckable(true); 404 | btn->setChecked(false); 405 | } 406 | 407 | btn->move(sx,sy); 408 | btn->resize(buttonWidth, buttonHeight); 409 | btn->storeSize(); 410 | 411 | // btn->setNode(node); 412 | // cout << "ColorGroup: " << qPrintable(colorGroup) << endl; 413 | 414 | sx+=buttonWidth+rowSpacingX; 415 | 416 | emit buttonLoaded(btn); 417 | } 418 | else if (node.toElement().tagName()=="spacing") { 419 | 420 | QString widthHint = attributes.namedItem("width").toAttr().value(); 421 | QString heightHint = attributes.namedItem("height").toAttr().value(); 422 | 423 | 424 | if (spacingMap.contains(widthHint)) { 425 | int spacingWidth = spacingMap.value(widthHint); 426 | 427 | sx+=spacingWidth; 428 | 429 | 430 | } 431 | if (heightMap.contains(heightHint)) { 432 | int spacingHeight = heightMap.value(heightHint); 433 | 434 | if (spacingHeight>rowHeight) rowHeight = spacingHeight; 435 | 436 | } 437 | 438 | } 439 | 440 | //cout << "X=>"<"<max_sx)max_sx = sx; 445 | 446 | sy+=(rowHeight+rowSpacingY); 447 | sx=0+rowMarginLeft; 448 | 449 | if (row_buttons>total_cols)total_cols=row_buttons; 450 | 451 | } 452 | if (sy>max_sy) max_sy = sy; 453 | 454 | vPart->setBaseSize(max_sx, max_sy); 455 | 456 | emit partLoaded(vPart, total_rows, total_cols); 457 | 458 | 459 | 460 | } 461 | 462 | #include "themeloader.moc" 463 | -------------------------------------------------------------------------------- /src/keysymconvert.cpp: -------------------------------------------------------------------------------- 1 | /* $XFree86$ 2 | * This module converts keysym values into the corresponding ISO 10646 3 | * (UCS, Unicode) values. 4 | * 5 | * The array keysymtab[] contains pairs of X11 keysym values for graphical 6 | * characters and the corresponding Unicode value. The function 7 | * keysym2ucs() maps a keysym onto a Unicode value using a binary search, 8 | * therefore keysymtab[] must remain SORTED by keysym value. 9 | * 10 | * The keysym -> UTF-8 conversion will hopefully one day be provided 11 | * by Xlib via XmbLookupString() and should ideally not have to be 12 | * done in X applications. But we are not there yet. 13 | * 14 | * We allow to represent any UCS character in the range U-00000000 to 15 | * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. 16 | * This admittedly does not cover the entire 31-bit space of UCS, but 17 | * it does cover all of the characters up to U-10FFFF, which can be 18 | * represented by UTF-16, and more, and it is very unlikely that higher 19 | * UCS codes will ever be assigned by ISO. So to get Unicode character 20 | * U+ABCD you can directly use keysym 0x0100abcd. 21 | * 22 | * NOTE: The comments in the table below contain the actual character 23 | * encoded in UTF-8, so for viewing and editing best use an editor in 24 | * UTF-8 mode. 25 | * 26 | * Author: Markus G. Kuhn , 27 | * University of Cambridge, April 2001 28 | * 29 | * Special thanks to Richard Verhoeven for preparing 30 | * an initial draft of the mapping table. 31 | * 32 | * This software is in the public domain. Share and enjoy! 33 | * 34 | * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl) 35 | */ 36 | 37 | #include "keysymconvert.h" 38 | 39 | struct codepair { 40 | unsigned short keysym; 41 | unsigned short ucs; 42 | } keysymtab[] = { 43 | { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ 44 | { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ 45 | { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ 46 | { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ 47 | { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ 48 | { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ 49 | { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ 50 | { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ 51 | { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ 52 | { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ 53 | { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ 54 | { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ 55 | { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ 56 | { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ 57 | { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ 58 | { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ 59 | { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ 60 | { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ 61 | { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ 62 | { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ 63 | { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ 64 | { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ 65 | { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ 66 | { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ 67 | { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ 68 | { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ 69 | { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ 70 | { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ 71 | { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ 72 | { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ 73 | { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ 74 | { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ 75 | { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ 76 | { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ 77 | { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ 78 | { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ 79 | { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ 80 | { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ 81 | { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ 82 | { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ 83 | { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ 84 | { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ 85 | { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ 86 | { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ 87 | { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ 88 | { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ 89 | { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ 90 | { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ 91 | { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ 92 | { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ 93 | { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ 94 | { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ 95 | { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ 96 | { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ 97 | { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ 98 | { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ 99 | { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ 100 | { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ 101 | { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ 102 | { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ 103 | { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ 104 | { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ 105 | { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ 106 | { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ 107 | { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ 108 | { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ 109 | { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ 110 | { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ 111 | { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ 112 | { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ 113 | { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ 114 | { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ 115 | { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ 116 | { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ 117 | { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ 118 | { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ 119 | { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ 120 | { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ 121 | { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ 122 | { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ 123 | { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ 124 | { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ 125 | { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ 126 | { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ 127 | { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ 128 | { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ 129 | { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ 130 | { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ 131 | { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ 132 | { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ 133 | { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ 134 | { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ 135 | { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ 136 | { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ 137 | { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ 138 | { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ 139 | { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ 140 | { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ 141 | { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ 142 | { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ 143 | { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ 144 | { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ 145 | { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ 146 | { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ 147 | { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ 148 | { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ 149 | { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ 150 | { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ 151 | { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ 152 | { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ 153 | { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ 154 | { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ 155 | { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ 156 | { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ 157 | { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ 158 | { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ 159 | { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ 160 | { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ 161 | { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ 162 | { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ 163 | { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ 164 | { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ 165 | { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ 166 | { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ 167 | { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ 168 | { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ 169 | { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ 170 | { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ 171 | { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ 172 | { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ 173 | { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ 174 | { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ 175 | { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ 176 | { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ 177 | { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ 178 | { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ 179 | { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ 180 | { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ 181 | { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ 182 | { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ 183 | { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ 184 | { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ 185 | { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ 186 | { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ 187 | { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ 188 | { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ 189 | { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ 190 | { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ 191 | { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ 192 | { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ 193 | { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ 194 | { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ 195 | { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ 196 | { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ 197 | { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ 198 | { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ 199 | { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ 200 | { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ 201 | { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ 202 | { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ 203 | { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ 204 | { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ 205 | { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ 206 | { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ 207 | { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ 208 | { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ 209 | { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ 210 | { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ 211 | { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ 212 | { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ 213 | { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ 214 | { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ 215 | { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ 216 | { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ 217 | { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ 218 | { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ 219 | { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ 220 | { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ 221 | { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ 222 | { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ 223 | { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ 224 | { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ 225 | { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ 226 | { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ 227 | { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ 228 | { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ 229 | { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ 230 | { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ 231 | { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ 232 | { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ 233 | { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ 234 | { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ 235 | { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ 236 | { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ 237 | { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ 238 | { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ 239 | { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ 240 | { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ 241 | { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ 242 | { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ 243 | { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ 244 | { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ 245 | { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ 246 | { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ 247 | { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ 248 | { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ 249 | { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ 250 | { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ 251 | { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ 252 | { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ 253 | { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ 254 | { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ 255 | { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ 256 | { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ 257 | { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ 258 | { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ 259 | { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ 260 | { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ 261 | { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ 262 | { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ 263 | { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ 264 | { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ 265 | { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ 266 | { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ 267 | { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ 268 | { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ 269 | { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ 270 | { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ 271 | { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ 272 | { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ 273 | { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ 274 | { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ 275 | { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ 276 | { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ 277 | { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ 278 | { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ 279 | { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ 280 | { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ 281 | { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ 282 | { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ 283 | { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ 284 | { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ 285 | { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ 286 | { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ 287 | { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ 288 | { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ 289 | { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ 290 | { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ 291 | { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ 292 | { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ 293 | { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ 294 | { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ 295 | { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ 296 | { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ 297 | { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ 298 | { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ 299 | { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ 300 | { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ 301 | { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ 302 | { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ 303 | { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ 304 | { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ 305 | { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ 306 | { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ 307 | { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ 308 | { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ 309 | { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ 310 | { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ 311 | { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ 312 | { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ 313 | { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ 314 | { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ 315 | { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ 316 | { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ 317 | { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ 318 | { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ 319 | { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ 320 | { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ 321 | { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ 322 | { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ 323 | { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ 324 | { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ 325 | { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ 326 | { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ 327 | { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ 328 | { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ 329 | { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ 330 | { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ 331 | { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ 332 | { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ 333 | { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ 334 | { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ 335 | { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ 336 | { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ 337 | { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ 338 | { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ 339 | { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ 340 | { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ 341 | { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ 342 | { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ 343 | { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ 344 | { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ 345 | { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ 346 | { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ 347 | { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ 348 | { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ 349 | { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ 350 | { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ 351 | { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ 352 | { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ 353 | { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ 354 | { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ 355 | { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ 356 | { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ 357 | { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ 358 | { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ 359 | { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ 360 | { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ 361 | { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ 362 | { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ 363 | { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ 364 | { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ 365 | { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ 366 | { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ 367 | { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ 368 | { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ 369 | { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ 370 | { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ 371 | { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ 372 | { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ 373 | { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ 374 | { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ 375 | { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ 376 | { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ 377 | { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ 378 | { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ 379 | { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ 380 | { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ 381 | { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ 382 | { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ 383 | { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ 384 | { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ 385 | { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ 386 | { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ 387 | { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ 388 | { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ 389 | { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ 390 | { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ 391 | { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ 392 | { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ 393 | { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ 394 | { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ 395 | { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ 396 | { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ 397 | { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ 398 | { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ 399 | { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ 400 | { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ 401 | { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ 402 | { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ 403 | { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ 404 | { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ 405 | { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ 406 | { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ 407 | { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ 408 | { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ 409 | { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ 410 | { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ 411 | { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ 412 | { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ 413 | { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ 414 | { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ 415 | { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ 416 | { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ 417 | { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ 418 | { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ 419 | { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ 420 | { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ 421 | { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ 422 | { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ 423 | { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ 424 | { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ 425 | { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ 426 | { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ 427 | { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ 428 | { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ 429 | { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ 430 | { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ 431 | { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ 432 | { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ 433 | { 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */ 434 | { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ 435 | { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ 436 | { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ 437 | { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ 438 | { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ 439 | { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */ 440 | { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */ 441 | { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */ 442 | { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */ 443 | { 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */ 444 | { 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */ 445 | { 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */ 446 | { 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */ 447 | { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */ 448 | { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */ 449 | /* 0x08b1 topleftsummation ? ??? */ 450 | /* 0x08b2 botleftsummation ? ??? */ 451 | /* 0x08b3 topvertsummationconnector ? ??? */ 452 | /* 0x08b4 botvertsummationconnector ? ??? */ 453 | /* 0x08b5 toprightsummation ? ??? */ 454 | /* 0x08b6 botrightsummation ? ??? */ 455 | /* 0x08b7 rightmiddlesummation ? ??? */ 456 | { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ 457 | { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ 458 | { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ 459 | { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ 460 | { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ 461 | { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ 462 | { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ 463 | { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ 464 | { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ 465 | { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ 466 | { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ 467 | { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ 468 | { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ 469 | { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ 470 | { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ 471 | { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ 472 | { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ 473 | { 0x08dd, 0x222a }, /* union ∪ UNION */ 474 | { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ 475 | { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ 476 | { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ 477 | { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ 478 | { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ 479 | { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ 480 | { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ 481 | { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ 482 | /* 0x09df blank ? ??? */ 483 | { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ 484 | { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ 485 | { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ 486 | { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ 487 | { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ 488 | { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ 489 | { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ 490 | { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ 491 | { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ 492 | { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ 493 | { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ 494 | { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ 495 | { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ 496 | { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ 497 | { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ 498 | { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ 499 | { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ 500 | { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ 501 | { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ 502 | { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ 503 | { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ 504 | { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ 505 | { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ 506 | { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ 507 | { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ 508 | { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ 509 | { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ 510 | { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ 511 | { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ 512 | { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ 513 | { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ 514 | { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ 515 | { 0x0aaa, 0x2013 }, /* endash – EN DASH */ 516 | /* 0x0aac signifblank ? ??? */ 517 | { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ 518 | { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ 519 | { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ 520 | { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ 521 | { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ 522 | { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ 523 | { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ 524 | { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ 525 | { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ 526 | { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ 527 | { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ 528 | { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ 529 | { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ 530 | /* 0x0abd decimalpoint ? ??? */ 531 | { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ 532 | /* 0x0abf marker ? ??? */ 533 | { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ 534 | { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ 535 | { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ 536 | { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ 537 | { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ 538 | { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ 539 | /* 0x0acb trademarkincircle ? ??? */ 540 | { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ 541 | { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ 542 | { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ 543 | { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ 544 | { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ 545 | { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ 546 | { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ 547 | { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ 548 | { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ 549 | { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ 550 | { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ 551 | { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ 552 | /* 0x0ada hexagram ? ??? */ 553 | { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ 554 | { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ 555 | { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ 556 | { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ 557 | { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ 558 | { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ 559 | { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ 560 | { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ 561 | { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ 562 | { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ 563 | { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ 564 | { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ 565 | { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ 566 | { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ 567 | { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ 568 | { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ 569 | { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ 570 | { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ 571 | { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ 572 | { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ 573 | { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ 574 | { 0x0af1, 0x2020 }, /* dagger † DAGGER */ 575 | { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ 576 | { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ 577 | { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ 578 | { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ 579 | { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ 580 | { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ 581 | { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ 582 | { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ 583 | { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ 584 | { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ 585 | { 0x0afc, 0x2038 }, /* caret ‸ CARET */ 586 | { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ 587 | { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ 588 | /* 0x0aff cursor ? ??? */ 589 | { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ 590 | { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ 591 | { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ 592 | { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ 593 | { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ 594 | { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ 595 | { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ 596 | { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ 597 | { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ 598 | { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ 599 | { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ 600 | { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ 601 | { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ 602 | { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ 603 | { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ 604 | { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ 605 | { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ 606 | { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ 607 | { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ 608 | { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ 609 | { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ 610 | { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ 611 | { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ 612 | { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ 613 | { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ 614 | { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ 615 | { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ 616 | { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ 617 | { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ 618 | { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ 619 | { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ 620 | { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ 621 | { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ 622 | { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ 623 | { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ 624 | { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ 625 | { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ 626 | { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ 627 | { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ 628 | { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ 629 | { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ 630 | { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ 631 | { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ 632 | { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ 633 | { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ 634 | { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ 635 | { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ 636 | { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ 637 | { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ 638 | { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ 639 | { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ 640 | { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ 641 | { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ 642 | { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ 643 | { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ 644 | { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ 645 | { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ 646 | { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ 647 | { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ 648 | { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ 649 | { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ 650 | { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ 651 | { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ 652 | { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ 653 | { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ 654 | { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ 655 | { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ 656 | { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ 657 | { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ 658 | { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ 659 | { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ 660 | { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ 661 | { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ 662 | { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ 663 | { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ 664 | { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ 665 | { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ 666 | { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ 667 | { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ 668 | { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ 669 | { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ 670 | { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ 671 | { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ 672 | { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ 673 | { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ 674 | { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ 675 | { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ 676 | { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ 677 | { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ 678 | { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ 679 | { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ 680 | { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ 681 | { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ 682 | { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ 683 | { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ 684 | { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ 685 | { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ 686 | { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ 687 | { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ 688 | { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ 689 | { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ 690 | { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ 691 | { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ 692 | { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ 693 | { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ 694 | /* 0x0dde Thai_maihanakat_maitho ? ??? */ 695 | { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ 696 | { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ 697 | { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ 698 | { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ 699 | { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ 700 | { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ 701 | { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ 702 | { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ 703 | { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ 704 | { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ 705 | { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ 706 | { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ 707 | { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ 708 | { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ 709 | { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ 710 | { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ 711 | { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ 712 | { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ 713 | { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ 714 | { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ 715 | { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ 716 | { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ 717 | { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ 718 | { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ 719 | { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ 720 | { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ 721 | { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ 722 | { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ 723 | { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ 724 | { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ 725 | { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ 726 | { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ 727 | { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ 728 | { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ 729 | { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ 730 | { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ 731 | { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ 732 | { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ 733 | { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ 734 | { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ 735 | { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ 736 | { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ 737 | { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ 738 | { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ 739 | { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ 740 | { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ 741 | { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ 742 | { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ 743 | { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ 744 | { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ 745 | { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ 746 | { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ 747 | { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ 748 | { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ 749 | { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ 750 | { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ 751 | { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ 752 | { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ 753 | { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ 754 | { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ 755 | { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ 756 | { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ 757 | { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ 758 | { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ 759 | { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ 760 | { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ 761 | { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ 762 | { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ 763 | { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ 764 | { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ 765 | { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ 766 | { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ 767 | { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ 768 | { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ 769 | { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ 770 | { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ 771 | { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ 772 | { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ 773 | { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ 774 | { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ 775 | { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ 776 | { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ 777 | { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ 778 | { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ 779 | { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ 780 | { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ 781 | { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ 782 | { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ 783 | { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ 784 | { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ 785 | { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ 786 | { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ 787 | { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ 788 | { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ 789 | { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ 790 | { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ 791 | { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ 792 | { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ 793 | { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ 794 | { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ 795 | { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ 796 | { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ 797 | { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ 798 | { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ 799 | { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ 800 | { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ 801 | { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ 802 | { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ 803 | { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ 804 | { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ 805 | { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ 806 | { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ 807 | { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ 808 | { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ 809 | { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ 810 | { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ 811 | { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ 812 | { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ 813 | { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ 814 | { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ 815 | { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ 816 | }; 817 | 818 | long KeySymConvert::convert(KeySym keysym) 819 | { 820 | int min = 0; 821 | int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; 822 | int mid; 823 | 824 | /* first check for Latin-1 characters (1:1 mapping) */ 825 | if ((keysym >= 0x0020 && keysym <= 0x007e) || 826 | (keysym >= 0x00a0 && keysym <= 0x00ff)) 827 | return keysym; 828 | 829 | /* also check for directly encoded 24-bit UCS characters */ 830 | if ((keysym & 0xff000000) == 0x01000000) 831 | return keysym & 0x00ffffff; 832 | 833 | /* binary search in table */ 834 | while (max >= min) { 835 | mid = (min + max) / 2; 836 | if (keysymtab[mid].keysym < keysym) 837 | min = mid + 1; 838 | else if (keysymtab[mid].keysym > keysym) 839 | max = mid - 1; 840 | else { 841 | /* found it */ 842 | return keysymtab[mid].ucs; 843 | } 844 | } 845 | 846 | /* no matching Unicode value found */ 847 | return -1; 848 | } 849 | --------------------------------------------------------------------------------