/* AbiSource Program Utilities * Copyright (C) 1998-2000 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include #include "ut_types.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "ev_EditBinding.h" #include "ev_EditEventMapper.h" #include "ev_EditMethod.h" #include "xav_View.h" #include "ev_NamedVirtualKey.h" #include "ev_UnixKeyboard.h" #include "ev_UnixKeysym2ucs.cpp" #include "xap_EncodingManager.h" #include"ut_mbtowc.h" ////////////////////////////////////////////////////////////////// static EV_EditBits s_mapVirtualKeyCodeToNVK(gint keyval); static bool s_isVirtualKeyCode(gint keyval); static GdkModifierType s_getAltMask(void); ////////////////////////////////////////////////////////////////// // This is used to remember the modifier mask (GDK_MODx_MASK) that // is bound to the Alt keys. We load this once per session. // // TODO Figure out if GTK/GDK can send us a MappingNotify event. // TODO If so, recompute this value. // static GdkModifierType s_alt_mask = GDK_MODIFIER_MASK; // bogus value GdkModifierType ev_UnixKeyboard::getAltModifierMask(void) { return s_alt_mask; } ////////////////////////////////////////////////////////////////// ev_UnixKeyboard::ev_UnixKeyboard(EV_EditEventMapper* pEEM) : EV_Keyboard(pEEM) { if (s_alt_mask == GDK_MODIFIER_MASK) s_alt_mask = s_getAltMask(); } ev_UnixKeyboard::~ev_UnixKeyboard(void) { } bool ev_UnixKeyboard::keyPressEvent(AV_View* pView, GdkEventKey* e) { EV_EditBits state = 0; EV_EditEventMapperResult result; EV_EditMethod * pEM; if (e->state & GDK_SHIFT_MASK) state |= EV_EMS_SHIFT; if (e->state & GDK_CONTROL_MASK) state |= EV_EMS_CONTROL; if (e->state & (s_alt_mask)) state |= EV_EMS_ALT; //UT_DEBUGMSG(("KeyPressEvent: keyval=%x state=%x\n",e->keyval,state)); if (s_isVirtualKeyCode(e->keyval)) { EV_EditBits nvk = s_mapVirtualKeyCodeToNVK(e->keyval); switch (nvk) { case EV_NVK__IGNORE__: return false; default: result = m_pEEM->Keystroke((UT_uint32)EV_EKP_PRESS|state|nvk,&pEM); switch (result) { case EV_EEMR_BOGUS_START: // If it is a bogus key and we don't have a sequence in // progress, we should let the system handle it // (this lets things like ALT-F4 work). return false; case EV_EEMR_BOGUS_CONT: // If it is a bogus key but in the middle of a sequence, // we should silently eat it (this is to prevent things // like Control-X ALT-F4 from killing us -- if they want // to kill us, fine, but they shouldn't be in the middle // of a sequence). return true; case EV_EEMR_COMPLETE: UT_ASSERT(pEM); //UT_DEBUGMSG(("invokeKeyboardMethod (1)\n")); invokeKeyboardMethod(pView,pEM,0,0); // no char data to offer return true; case EV_EEMR_INCOMPLETE: return true; default: UT_ASSERT(0); return true; } } } else { UT_uint16 charData = e->keyval; //UT_DEBUGMSG(("UnixKeyboard::pressKeyEvent: key value %x\n", charData)); if(charData>0xff || charData == 0) result = m_pEEM->Keystroke(EV_EKP_PRESS|state|'a',&pEM); else result = m_pEEM->Keystroke(EV_EKP_PRESS|state|charData,&pEM); switch (result) { case EV_EEMR_BOGUS_START: // If it is a bogus key and we don't have a sequence in // progress, we should let the system handle it // (this lets things like ALT-F4 work). return false; case EV_EEMR_BOGUS_CONT: // If it is a bogus key but in the middle of a sequence, // we should silently eat it (this is to prevent things // like Control-X ALT-F4 from killing us -- if they want // to kill us, fine, but they shouldn't be in the middle // of a sequence). return true; case EV_EEMR_COMPLETE: { UT_ASSERT(pEM); UT_UCSChar *ucs = NULL; char *mbs = e->string; int mLength = strlen(mbs); int uLength = 0; /* if gdk fails to translate, then we will try to do this ourselves by calling kesym2ucs if the current locale is utf-8, we will also use keysym2ucs */ if(XAP_EncodingManager::get_instance()->isUnicodeLocale() || mLength == 0) { UT_sint32 u = keysym2ucs(e->keyval); if(u == -1 || u > 0xFFFF) //conversion failed, or more than 16 bit requied { mLength = 0; } else { mLength = 1; ucs = new UT_UCSChar[1]; ucs[0] = u; } uLength = mLength; //UT_DEBUGMSG(("#TF: keyval=%x, ucs=%x\n", ucs[0])); } else { UT_Mbtowc m; ucs=new UT_UCSChar[mLength]; for(int i=0;i 0x0000FFFF) return false; //was true before CJK patch // // Causes immediate on keypress segfault?? if (keyval >= GDK_KP_Space && keyval <= GDK_KP_9 && keyval != GDK_KP_Enter) // number pad keys return false; if (keyval > 0xFF00) // see the above table return true; if (keyval > 0xFE00) // see the above table return true; UT_ASSERT(keyval <= 0xFD00); // we don't what to do with 3270 keys if (keyval == 0x0020) // special handling for ASCII-Space return true; return false; } static EV_EditBits s_mapVirtualKeyCodeToNVK(gint keyval) { // map the given virtual key into a "named virtual key". // these are referenced by NVK_ symbol so that the cross // platform code can properly refer to them. // there is also a set of Hardware Vendor ranges defined. // these appear to have stuff in the high word. (see {ap_,DEC,HP,Sun}keysym.h) // for now, we will ignore these. if (keyval > 0x0000FFFF) return EV_NVK__IGNORE__; if (keyval > 0xFF00) return s_Table_NVK_0xff[keyval - 0xFF00]; if (keyval > 0xFE00) return s_Table_NVK_0xfe[keyval - 0xFE00]; if (keyval == 0x0020) return EV_NVK_SPACE; UT_ASSERT(0); return EV_NVK__IGNORE__; } ////////////////////////////////////////////////////////////////// // deal with keyboard mapping oddities ////////////////////////////////////////////////////////////////// #include #include #include #include static GdkModifierType s_getAltMask(void) { ////////////////////////////////////////////////////////////////// // find out what modifier mask XL_Alt_{L,R} are bound to. ////////////////////////////////////////////////////////////////// int alt_mask = 0; Display * display = GDK_DISPLAY(); KeyCode kcAltL = XKeysymToKeycode(display,XK_Alt_L); KeyCode kcAltR = XKeysymToKeycode(display,XK_Alt_R); XModifierKeymap * pModMap = XGetModifierMapping(display); int mkpm = pModMap->max_keypermod; int k,m; int mAltL=-1; int mAltR=-1; for (m=0; m<8; m++) { for (k=0; kmodifiermap[m*mkpm + k]; if (kcAltL && (code == kcAltL)) mAltL = m; if (kcAltR && (code == kcAltR)) mAltR = m; } } switch (mAltL) { default: // Should not happen... case -1: // Alt_L is not a modifier key ?? case 0: // Alt_L is mapped to SHIFT ?? case 1: // Alt_L is mapped to (Caps)LOCK ?? case 2: // Alt_L is mapped to CONTROL ?? break; // ... ignore this key. case 3: alt_mask |= GDK_MOD1_MASK; break; case 4: alt_mask |= GDK_MOD2_MASK; break; case 5: alt_mask |= GDK_MOD3_MASK; break; case 6: alt_mask |= GDK_MOD4_MASK; break; case 7: alt_mask |= GDK_MOD5_MASK; break; } switch (mAltR) { default: // Should not happen... case -1: // Alt_R is not a modifier key ?? case 0: // Alt_R is mapped to SHIFT ?? case 1: // Alt_R is mapped to (Caps)LOCK ?? case 2: // Alt_R is mapped to CONTROL ?? break; // ... ignore this key. case 3: alt_mask |= GDK_MOD1_MASK; break; case 4: alt_mask |= GDK_MOD2_MASK; break; case 5: alt_mask |= GDK_MOD3_MASK; break; case 6: alt_mask |= GDK_MOD4_MASK; break; case 7: alt_mask |= GDK_MOD5_MASK; break; } XFreeModifiermap(pModMap); if (!alt_mask) // if nothing set, fall back to MOD1 alt_mask = GDK_MOD1_MASK; //UT_DEBUGMSG(("Keycodes for alt [l 0x%x][r 0x%x] using modifiers [%d %d] yields [0x%x]\n",kcAltL,kcAltR,mAltL-2,mAltR-2,alt_mask)); return (GdkModifierType)alt_mask; }