/* * LoadBindings * Copyright (C) 2007 by Martin Sevior * * 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. */ #ifdef ABI_PLUGIN_BUILTIN #define abi_plugin_register abipgn_loadbindings_register #define abi_plugin_unregister abipgn_loadbindings_unregister #define abi_plugin_supports_version abipgn_loadbindings_supports_version #endif #include #include #include #include #include #include #include "xap_Module.h" #include "xap_App.h" #include "xap_Frame.h" #include "fv_View.h" #include "ev_EditMethod.h" #include "ie_imp.h" #include "ie_exp.h" #include "ie_types.h" #include "ap_Convert.h" #include "ap_EditMethods.h" #include "ev_EditBits.h" #include "LoadBindings.h" #include "ap_LoadBindings.h" #include "ut_bytebuf.h" ABI_PLUGIN_DECLARE (LoadBindings) #define RES_TO_STATUS(a) ((a) ? 0 : -1) static bool LoadBindings_invoke (AV_View * v, EV_EditMethodCallData * d); static bool SetBindings_invoke (AV_View * v, EV_EditMethodCallData * d); // // LoadBindings_registerMethod() // ----------------------- // Adds AbiCommand_invoke to the EditMethod list // static void LoadBindings_registerMethod () { // First we need to get a pointer to the application itself. XAP_App *pApp = XAP_App::getApp (); // Create an EditMethod that will link our method's name with // it's callback function. This is used to link the name to // the callback. EV_EditMethod *myEditMethod = new EV_EditMethod ("LoadBindings_invoke", // name of callback function LoadBindings_invoke, // callback function itself. 0, // no additional data required. "" // description -- allegedly never used for anything ); // Now we need to get the EditMethod container for the application. // This holds a series of Edit Methods and links names to callbacks. EV_EditMethodContainer *pEMC = pApp->getEditMethodContainer (); // We have to add our EditMethod to the application's EditMethodList // so that the application will know what callback to call when a call pEMC->addEditMethod (myEditMethod); myEditMethod = new EV_EditMethod ("SetBindings_invoke", // name of callback function SetBindings_invoke, // callback function itself. 0, // no additional data required. "" // description -- allegedly never used for anything ); pEMC->addEditMethod (myEditMethod); } static void LoadBindings_RemoveFromMethods () { // First we need to get a pointer to the application itself. XAP_App *pApp = XAP_App::getApp (); // remove the edit method EV_EditMethodContainer *pEMC = pApp->getEditMethodContainer (); EV_EditMethod *pEM = ev_EditMethod_lookup ("LoadBindings_invoke"); pEMC->removeEditMethod (pEM); DELETEP (pEM); pEM = ev_EditMethod_lookup ("SetBindings_invoke"); pEMC->removeEditMethod (pEM); DELETEP (pEM); } // ----------------------------------------------------------------------- // // Abiword Plugin Interface // // ----------------------------------------------------------------------- ABI_FAR_CALL int abi_plugin_register (XAP_ModuleInfo * mi) { mi->name = "LoadBindings"; mi->desc = "This allows Keybindings to be loaded from an Ascii file"; mi->version = ABI_VERSION_STRING; mi->author = "Martin Sevior "; mi->usage = "LoadBindings_invoke"; LoadBindings_registerMethod (); return 1; } ABI_FAR_CALL int abi_plugin_unregister (XAP_ModuleInfo * mi) { mi->name = 0; mi->desc = 0; mi->version = 0; mi->author = 0; mi->usage = 0; LoadBindings_RemoveFromMethods (); return 1; } ABI_FAR_CALL int abi_plugin_supports_version (UT_uint32 major, UT_uint32 minor, UT_uint32 release) { return 1; } // ----------------------------------------------------------------------- // // LoadBindings Invocation Code // // ----------------------------------------------------------------------- // // LoadBindings_invoke // ------------------- // This is the function that loads the keybindings from an ascii file to // a named set of keybindings. // static bool LoadBindings_invoke (AV_View * v, EV_EditMethodCallData * d) { LoadBindings loadBindings(d); bool b = loadBindings.process(); return b; } // // SetBindings_invoke // ------------------- // This functions sets the keybindings to the name passed through // EV_EditMethodCallData * // static bool SetBindings_invoke (AV_View * v, EV_EditMethodCallData * d) { XAP_App * pApp = XAP_App::getApp(); UT_String sName; UT_UCS4String ucs4(reinterpret_cast(d->m_pData),d->m_dataLength); return (pApp->setInputMode(ucs4.utf8_str()) >= 0); } LoadBindings::LoadBindings (EV_EditMethodCallData * d) : m_sData(""), m_sName(""), m_pNewMap(NULL), m_iPos(0) { m_pApp = XAP_App::getApp (); UT_UCS4String ucs4(reinterpret_cast(d->m_pData),d->m_dataLength); m_sData = ucs4.utf8_str(); xxx_UT_DEBUGMSG(("Text is %s \n",m_sData.c_str())); xxx_UT_DEBUGMSG(("Length is %d \n",d->m_dataLength)); } LoadBindings::~LoadBindings (void) { } /*! * Process the ascii file and load the bindings. */ bool LoadBindings::process (void) { UT_String nextLine; UT_GenericVector tokens; bool bFoundName = false; while(getNextLine(nextLine)) { bool b = tokenizeString(tokens, nextLine,","); if(b) { UT_String tok0 = *tokens[0]; if(g_strcasecmp(tok0.substr(0,2).c_str(),"//") == 0) { continue; } if(g_strcasecmp(tok0.c_str(),"name") == 0) { m_sName = *tokens[1]; if(!bFoundName) { AP_BindingSet * pBSet = static_cast(m_pApp->getBindingSet()); m_pNewMap = pBSet->createMap(m_sName.c_str()); bFoundName = true; break; } } } } if(!bFoundName) return false; resetLine(); while(getNextLine(nextLine)) { bool b = tokenizeString(tokens, nextLine,","); if(b) { UT_String tok0 = *tokens[0]; xxx_UT_DEBUGMSG(("tok0 is %s \n",tok0.c_str())); if(g_strcasecmp(tok0.substr(0,2).c_str(),"//") == 0) { continue; } if(g_strcasecmp(tok0.c_str(),"name") == 0) { continue; } if(g_strcasecmp(tok0.c_str(),"mse") == 0) { EV_EditMouseButton eMseButton = 0; EV_EditMouseOp eMseOp = 0; EV_EditMouseContext eMseContext = 0; if(!tokens[1] || tokens[1]->size() == 0) { continue; } else if(g_strcasecmp(tokens[1]->c_str(),"B0") == 0) { eMseButton = EV_EMB_BUTTON0; } else if(g_strcasecmp(tokens[1]->c_str(),"B1") == 0) { eMseButton = EV_EMB_BUTTON1; } else if(g_strcasecmp(tokens[1]->c_str(),"B2") == 0) { eMseButton = EV_EMB_BUTTON2; } else if(g_strcasecmp(tokens[1]->c_str(),"B3") == 0) { eMseButton = EV_EMB_BUTTON3; } else if(g_strcasecmp(tokens[1]->c_str(),"B4") == 0) { eMseButton = EV_EMB_BUTTON4; } else if(g_strcasecmp(tokens[1]->c_str(),"B5") == 0) { eMseButton = EV_EMB_BUTTON5; } eMseContext = getMseContext(*tokens[2]); UT_uint32 i = 3; eMseOp = EV_EMO_SINGLECLICK; EV_EditBits efull = eMseOp | eMseContext | eMseButton; for(i =3; (i<9) && (i< tokens.getItemCount());i++) { if(tokens[i] && tokens[i]->size() > 0) { gchar* sz = g_strdup(tokens[i]->c_str()); gchar * szStrip = g_strstrip(sz); if(strlen(szStrip) > 0) m_pNewMap->setBinding(efull,szStrip); g_free(sz); } efull += EV_EMO_SINGLECLICK; } } if(g_strcasecmp(tok0.c_str(),"NVK") == 0) { EV_EditBits vK = getNamedVKey(*tokens[1]); EV_EditModifierState eMseMod = 0; for(UT_uint32 i =2; (i<10) && (i< tokens.getItemCount());i++) { EV_EditBits efull = vK | EV_EKP_NAMEDKEY | eMseMod; eMseMod += EV_EMS_SHIFT; if(tokens[i] && tokens[i]->size() > 0) { gchar* sz = g_strdup(tokens[i]->c_str()); gchar * szStrip = g_strstrip(sz); if(strlen(szStrip) > 0) { m_pNewMap->setBinding(efull,szStrip); } g_free(sz); } } } if(g_strcasecmp(tok0.c_str(),"key") == 0) { EV_EditBits vK = getKey(*tokens[1]); EV_EditModifierState eMseMod = 0; for(UT_uint32 i =2; (i<6) && (i< tokens.getItemCount());i++) { EV_EditBits efull = vK | EV_EKP_PRESS | eMseMod; eMseMod += EV_EMS_CONTROL; if(tokens[i] && tokens[i]->size() > 0) { gchar* sz = g_strdup(tokens[i]->c_str()); gchar * szStrip = g_strstrip(sz); if(strlen(szStrip) > 0) { m_pNewMap->setBinding(efull,szStrip); } g_free(sz); } } } } } clearTokenVector(tokens); return true; } EV_EditMouseContext LoadBindings::getMseContext(UT_String & sStr) { gchar * sz = g_strdup(sStr.c_str()); gchar ** szToks = g_strsplit(sz," ",6); if(szToks[0] == 0) { g_free(sz); g_strfreev(szToks); return EV_EMC_UNKNOWN; } gchar * szStrip = g_strstrip(szToks[0]); EV_EditMouseContext eCon = EV_EMC_UNKNOWN; if(strlen(szStrip ) == 0) { g_free(sz); eCon = EV_EMC_UNKNOWN; g_strfreev(szToks); return EV_EMC_UNKNOWN; } if(g_strcasecmp(szStrip,"CU") == 0) { eCon = EV_EMC_UNKNOWN; } else if(g_strcasecmp(szStrip,"CT") == 0) { eCon = EV_EMC_TEXT; } else if(g_strcasecmp(szStrip,"CM") == 0) { eCon = EV_EMC_MISSPELLEDTEXT; } else if(g_strcasecmp(szStrip,"CL") == 0) { eCon = EV_EMC_LEFTOFTEXT; } else if(g_strcasecmp(szStrip,"CL") == 0) { eCon = EV_EMC_LEFTOFTEXT; } else if(g_strcasecmp(szStrip,"CR") == 0) { eCon = EV_EMC_RIGHTOFTEXT; } else if(g_strcasecmp(szStrip,"CI") == 0) { eCon = EV_EMC_IMAGE; } else if(g_strcasecmp(szStrip,"CZ") == 0) { eCon = EV_EMC_IMAGESIZE; } else if(g_strcasecmp(szStrip,"CF") == 0) { eCon = EV_EMC_FIELD; } else if(g_strcasecmp(szStrip,"CH") == 0) { eCon = EV_EMC_HYPERLINK; } else if(g_strcasecmp(szStrip,"CV") == 0) { eCon = EV_EMC_REVISION; } else if(g_strcasecmp(szStrip,"CTV") == 0) { eCon = EV_EMC_VLINE; } else if(g_strcasecmp(szStrip,"CTH") == 0) { eCon = EV_EMC_HLINE; } else if(g_strcasecmp(szStrip,"CTF") == 0) { eCon = EV_EMC_FRAME; } else if(g_strcasecmp(szStrip,"CVD") == 0) { eCon = EV_EMC_VISUALTEXTDRAG; } else if(g_strcasecmp(szStrip,"CTC") == 0) { eCon = EV_EMC_TOPCELL; } else if(g_strcasecmp(szStrip,"CTO") == 0) { eCon = EV_EMC_TOC; } else if(g_strcasecmp(szStrip,"CPO") == 0) { eCon = EV_EMC_POSOBJECT; } else if(g_strcasecmp(szStrip,"CMA") == 0) { eCon = EV_EMC_MATH; } else if(g_strcasecmp(szStrip,"CEM") == 0) { eCon = EV_EMC_EMBED; } EV_EditModifierState eMod = 0; UT_sint32 i = 1; while(szToks[i]) { szStrip = g_strstrip(szToks[i]); if(strlen(szStrip) == 0) { i++; continue; } if(g_strcasecmp(szStrip,"S") == 0) { eMod = eMod | EV_EMS_SHIFT; } else if(g_strcasecmp(szStrip,"C") == 0) { eMod = eMod | EV_EMS_CONTROL; } else if(g_strcasecmp(szStrip,"A") == 0) { eMod = eMod | EV_EMS_ALT; } i++; } g_free(sz); g_strfreev(szToks); return eCon | eMod; } static const char * s_Table[] = { "", // must be at index zero "backspace", "space", "tab", "return", "escape", "pageup", "pagedown", "end", "home", "left", "up", "right", "down", "insert", "delete", "help", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "DeadGrave", "DeadAcute", "DeadCircumflex", "DeadTilde", "DeadMacron", "DeadBreve", "DeadAboveDot", "DeadDiaeresis", "DeadDoubleAcute", "DeadCaron", "DeadCedilla", "DeadOgonek", "DeadIota", "MenuShortCut" // TODO as other items are added to ev_NamedVirtualKey, add items here. }; EV_EditKeyPress LoadBindings::getNamedVKey(UT_String & sStr) { xxx_UT_DEBUGMSG(("Looking for keyname %s \n",sStr.c_str())); for (UT_uint32 k=1; k & tok, UT_String & sStr, gchar * sSplit) { gchar * sz = g_strdup(sStr.c_str()); clearTokenVector(tok); gchar ** szToks = g_strsplit(sz,sSplit,20); UT_sint32 i = 0; if(szToks[i] == 0) return false; while(szToks[i]) { gchar * sz2 = g_strdup(szToks[i]); gchar * szStrip = g_strstrip(sz2); UT_String * pS = new UT_String(szStrip); xxx_UT_DEBUGMSG(("i= %d szStrip %s \n",i,szStrip)); tok.addItem(pS); g_free(sz2); i++; } g_free(sz); g_strfreev(szToks); return true; } /*! * clear the token vector pointed to by vecToks */ void LoadBindings::clearTokenVector (UT_GenericVector & vecToks) { UT_uint32 i = 0; for (i = 0; i < vecToks.getItemCount (); i++) { UT_String *pComm = vecToks.getNthItem (i); delete pComm; } vecToks.clear (); }