keyboard.cpp

00001 /**************
00002 FILE          : keyboard.cpp
00003 ***************
00004 PROJECT       : SaX2 - library interface
00005               :
00006 AUTHOR        : Marcus Schäfer <ms@suse.de>
00007               :
00008 BELONGS TO    : SaX2 - SuSE advanced X11 configuration 
00009               : 
00010               :
00011 DESCRIPTION   : native C++ class library to access SaX2
00012               : functionality. Easy to use interface for
00013               : //.../
00014               : - importing/exporting X11 configurations
00015               : - modifying/creating X11 configurations 
00016               : ---
00017               :
00018               :
00019 STATUS        : Status: Development
00020 **************/
00021 #include "keyboard.h"
00022 
00023 namespace SaX {
00024 //====================================
00025 // Constructor
00026 //------------------------------------
00027 SaXKeyRules::SaXKeyRules (QString rule): mLayouts(80) {
00028         // .../
00032         // ----
00033         mX11Dir = "/usr/lib/X11/";
00034         if (! access ("/usr/share/X11/xkb",R_OK|X_OK)) {
00035                 mX11Dir = "/usr/share/X11/";
00036         }
00037         loadRules (mX11Dir + QString("xkb/rules/%1").arg(rule));
00038 }
00039 
00040 //====================================
00041 // loadRules
00042 //------------------------------------
00043 void SaXKeyRules::loadRules(QString file) {
00044         // .../
00047         // ----
00048         static struct {
00049                 const char * locale;
00050                 const char * layout;
00051         } fixedLayouts[] = {
00052                 { "ben", "Bengali" },
00053                 { "ar" , "Arabic"  },
00054                 { "ir" , "Farsi"   },
00055                 { 0    , 0 }
00056         };
00057         char* locale = setlocale (LC_ALL,NULL);
00058         XkbRF_RulesPtr rules = XkbRF_Load (
00059                 QFile::encodeName(file).data(),
00060                 locale, true, true
00061         );
00062         if (! rules) {
00063                 excXKBLoadRulesFailed();
00064                 qError (errorString(),EXC_XKBLOADRULESFAILED);
00065                 return;
00066         }
00067         int i;
00068         for (i = 0; i < rules->models.num_desc; ++i) {
00069                 mModels.replace (
00070                         rules->models.desc[i].name,
00071                         new QString (qstrdup( rules->models.desc[i].desc))
00072                 );
00073         }
00074         for (i = 0; i < rules->layouts.num_desc; ++i) {
00075                 mLayouts.replace (
00076                         rules->layouts.desc[i].name,
00077                         new QString (qstrdup( rules->layouts.desc[i].desc))
00078                 );
00079         }
00080         for (i = 0; i < rules->options.num_desc; ++i) {
00081                 mOptions.replace (
00082                         rules->options.desc[i].name,
00083                         new QString (qstrdup( rules->options.desc[i].desc))
00084                 );
00085         }
00086         XkbRF_Free(rules, true);
00087         // ...
00088         // Knowing which variants we have won't help us
00089         // We want to know which particular variants are available for
00090         // each language
00091         // ---
00092         for(int i=0; fixedLayouts[i].layout != 0; i++ ) {
00093                 mLayouts.replace (
00094                         fixedLayouts[i].locale, new QString (fixedLayouts[i].layout)
00095                 );
00096         }
00097 }
00098 
00099 //====================================
00100 // getVariants
00101 //------------------------------------
00102 QList<QString> SaXKeyRules::getVariants (const QString& layout) {
00103         // .../
00106         // ----
00107         if ( layout.isEmpty() || ! getLayouts().find(layout) ) {
00108                 return QList<QString>();
00109         }
00110         QList<QString> result1;
00111         QStringList* r1 = mVarLists[layout];
00112         if ( r1 ) {
00113                 for ( QStringList::Iterator it=r1->begin(); it != r1->end(); ++it ) {
00114                         QString* item = new QString (*it);
00115                         result1.append (item);
00116                 }
00117                 return result1;
00118         }
00119         QList<QString> result2;
00120         QStringList* result = new QStringList();
00121         QString file = mX11Dir + "xkb/symbols/" + layout;
00122         QFile f(file);
00123         if (f.open(IO_ReadOnly)) {
00124                 QTextStream ts(&f);
00125                 QString line;
00126                 QString prev_line;
00127                 while (!ts.eof()) {
00128                         prev_line = line;
00129                         line = ts.readLine().simplifyWhiteSpace();
00130                         if (line[0] == '#' || line.left(2) == "//" || line.isEmpty()) {
00131                                 continue;
00132                         }
00133                         int pos = line.find("xkb_symbols");
00134                         if (pos < 0) {
00135                                 continue;
00136                         }
00137                         if ( prev_line.find("hidden") >=0 ) {
00138                                 continue;
00139                         }
00140                         pos = line.find('"', pos) + 1;
00141                         int pos2 = line.find('"', pos);
00142                         if ( pos < 0 || pos2 < 0 ) {
00143                                 continue;
00144                         }
00145                         result->append (
00146                                 line.mid(pos, pos2-pos)
00147                         );
00148                 }
00149                 f.close();
00150         }
00151         mVarLists.insert(layout, result);
00152         for ( QStringList::Iterator it=result->begin(); it != result->end();++it) {
00153                 QString* item = new QString (*it);
00154                 result2.append (item);
00155         }
00156         return result2;
00157 }
00158 
00159 //====================================
00160 // getModels
00161 //------------------------------------
00162 QDict<QString> SaXKeyRules::getModels  (void) {
00163         return mModels;
00164 }
00165 
00166 //====================================
00167 // getLayouts
00168 //------------------------------------
00169 QDict<QString> SaXKeyRules::getLayouts (void) {
00170         return mLayouts;
00171 }
00172 
00173 //====================================
00174 // getOptions
00175 //------------------------------------
00176 QDict<QString> SaXKeyRules::getOptions (void) {
00177         return mOptions;
00178 }
00179 
00180 //====================================
00181 // Constructor...
00182 //------------------------------------
00183 SaXManipulateKeyboard::SaXManipulateKeyboard (
00184         SaXImport* in, int kbd
00185 ) : SaXManipulateKeyboardIF () {
00186         // .../
00191         // ----
00192         if ( ! in ) {
00193                 excNullPointerArgument ();
00194                 qError (errorString(),EXC_NULLPOINTERARGUMENT);
00195                 return;
00196         }
00197         if ( in->getSectionID() != SAX_KEYBOARD ) {
00198                 excKeyboardImportBindFailed ( in->getSectionID() );
00199                 qError (errorString(),EXC_KEYBOARDIMPORTBINDFAILED);
00200                 return;
00201         }
00202         mImport = in;
00203         mKeyboard = kbd;
00204         mImport -> setID ( mKeyboard );
00205 }
00206 
00207 //====================================
00208 // set keyboard ID
00209 //------------------------------------
00210 bool SaXManipulateKeyboard::selectKeyboard (int ptr) {
00211         // .../
00214         // ----
00215         if (! mImport) {
00216                 return false;
00217         }
00218         if (mImport -> setID ( ptr )) {
00219                 mKeyboard = ptr;
00220                 return true;
00221         }
00222         return false;
00223 }
00224 
00225 //====================================
00226 // setXKBModel
00227 //------------------------------------
00228 void SaXManipulateKeyboard::setXKBModel (const QString& model) {
00229         // .../
00232         // ----
00233         if (! mImport) {
00234                 return;
00235         }
00236         mImport -> setItem ( "XkbModel",model );
00237 }
00238 
00239 //====================================
00240 // setXKBLayout
00241 //------------------------------------
00242 void SaXManipulateKeyboard::setXKBLayout (const QString& layout) {
00243         // .../
00246         // ----
00247         if (! mImport) {
00248                 return;
00249         }
00250         mImport -> setItem ( "XkbLayout",layout );
00251 }
00252 
00253 //====================================
00254 // addXKBLayout
00255 //------------------------------------
00256 void SaXManipulateKeyboard::addXKBLayout (const QString& layout) {
00257         // .../
00261         // ----
00262         if (! mImport) {
00263                 return;
00264         }
00265         QString val;
00266         QString key ("XkbLayout");
00267         if (! mImport -> getItem (key).isEmpty()) {
00268                 val = mImport -> getItem (key);
00269         }
00270         QTextOStream (&val) << val << "," << layout;
00271         mImport -> setItem ( key,val );
00272 }
00273 
00274 //====================================
00275 // removeXKBLayout
00276 //------------------------------------
00277 void SaXManipulateKeyboard::removeXKBLayout (const QString& layout) {
00278         // .../
00281         // ----
00282         if (! mImport) {
00283                 return;
00284         }
00285         QString val (layout);
00286         QString key ("XkbLayout");
00287         if (! mImport -> getItem (key).isEmpty()) {
00288                 mImport -> removeItem (key,val);
00289         }
00290 }
00291 
00292 //====================================
00293 // setXKBOption
00294 //------------------------------------
00295 void SaXManipulateKeyboard::setXKBOption (const QString& option) {
00296         // .../
00299         // ----
00300         if (! mImport) {
00301                 return;
00302         }
00303         mImport -> setItem ( "XkbOptions",option );
00304 }
00305 
00306 //====================================
00307 // addXKBOption
00308 //------------------------------------
00309 void SaXManipulateKeyboard::addXKBOption (const QString& option) {
00310         // .../
00313         // ----
00314         if (! mImport) {
00315                 return;
00316         }
00317         QString val;
00318         QString key ("XkbOptions");
00319         if (! mImport -> getItem (key).isEmpty()) {
00320                 val = mImport -> getItem (key);
00321         }
00322         QTextOStream (&val) << val << "," << option;
00323         mImport -> setItem ( key,val );
00324 }
00325 
00326 //====================================
00327 // removeXKBOption
00328 //------------------------------------
00329 void SaXManipulateKeyboard::removeXKBOption (const QString& option) {
00330         // .../
00333         // ----
00334         if (! mImport) {
00335                 return;
00336         }
00337         QString val (option);
00338         QString key ("XkbOptions");
00339         if (! mImport -> getItem (key).isEmpty()) {
00340                 mImport -> removeItem (key,val);
00341         }
00342 }
00343 
00344 //====================================
00345 // setXKBVariant
00346 //------------------------------------
00347 void SaXManipulateKeyboard::setXKBVariant (
00348         const QString& layout, const QString& variant
00349 ) {
00350         // .../
00353         // ----
00354         if (! mImport) {
00355                 return;
00356         }
00357         int layoutCount = findLayout (layout);
00358         if (layoutCount < 0) {
00359                 excXKBLayoutUndefined (layout);
00360                 qError (errorString(),EXC_XKBLAYOUTUNDEFINED);
00361                 return;
00362         }
00363         QList<QString> vList = getXKBVariantList();
00364         QList<QString> lList = getXKBLayout();
00365         int varCount = 0;
00366         QStringList result;
00367         QListIterator<QString> it (lList);
00368         for (; it.current();++it) {
00369                 QString item;
00370                 if (vList.at(varCount)) {
00371                         item = *vList.at (varCount);
00372                 }
00373                 if (varCount == layoutCount) {
00374                         item = variant;
00375                 }
00376                 result += item;
00377                 varCount++;
00378         }
00379         mImport -> setItem ("XkbVariant",result.join(","));
00380 }
00381 
00382 //====================================
00383 // removeXKBVariant
00384 //------------------------------------
00385 void SaXManipulateKeyboard::removeXKBVariant ( const QString& layout ) {
00386         // .../
00389         // ----
00390         setXKBVariant (layout,"");
00391 }
00392 
00393 //====================================
00394 // setMapping
00395 //------------------------------------
00396 void SaXManipulateKeyboard::setMapping (
00397         const QString& type,const QString& mapping
00398 ) {
00399         // .../
00403         // ----
00404         if (! mImport) {
00405                 return;
00406         }
00407         QString key (type);
00408         QString map (mapping);
00409         if (
00410                 (key != XKB_LEFT_ALT)       &&
00411                 (key != XKB_RIGHT_ALT)      &&
00412                 (key != XKB_SCROLL_LOCK)    &&
00413                 (key != XKB_RIGHT_CTL)
00414         ) {
00415                 excInvalidArgument (type);
00416                 qError (errorString(),EXC_INVALIDARGUMENT);
00417                 return;
00418         }
00419         if (
00420                 (map != XKB_MAP_META)       &&
00421                 (map != XKB_MAP_COMPOSE)    &&
00422                 (map != XKB_MAP_MODESHIFT)  &&
00423                 (map != XKB_MAP_MODELOCK)   &&
00424                 (map != XKB_MAP_SCROLLLOCK) &&
00425                 (map != XKB_MAP_CONTROL)
00426         ) {
00427                 excInvalidArgument (mapping);
00428                 qError (errorString(),EXC_INVALIDARGUMENT);
00429                 return;
00430         }
00431         mImport -> setItem ( type,mapping );
00432 }
00433 
00434 //====================================
00435 // getDriver
00436 //------------------------------------
00437 QString SaXManipulateKeyboard::getDriver (void) {
00438         // .../
00440         // ----
00441         if (! mImport) {
00442                 return QString();
00443         }
00444         return mImport -> getItem ("Driver");
00445 }
00446 
00447 //====================================
00448 // getXKBOptionList
00449 //------------------------------------
00450 QList<QString> SaXManipulateKeyboard::getXKBOptionList (void) {
00451         // .../
00453         // ----
00454         if (! mImport) {
00455                 return QList<QString>();
00456         }
00457         QString options = mImport -> getItem ("XkbOptions");
00458         return createList (options);
00459 }
00460 
00461 //====================================
00462 // getXKBLayout
00463 //------------------------------------
00464 QList<QString> SaXManipulateKeyboard::getXKBLayout (void) {
00465         // .../
00468         // ----
00469         if (! mImport) {
00470                 return QList<QString>();
00471         }
00472         QString layouts = mImport -> getItem ("XkbLayout");
00473         return createList (layouts);
00474 }
00475 
00476 //====================================
00477 // getXKBVariantList
00478 //------------------------------------
00479 QList<QString> SaXManipulateKeyboard::getXKBVariantList (void) {
00480         // .../
00483         // ----
00484         if (! mImport) {
00485                 return QList<QString>();
00486         }
00487         QString variants = mImport -> getItem ("XkbVariant");
00488         return createList (variants);
00489 }
00490 
00491 //====================================
00492 // getXKBVariant for layout X
00493 //------------------------------------
00494 QString SaXManipulateKeyboard::getXKBVariant ( const QString& layout ) {
00495         // .../
00500         // ----
00501         if (! mImport) {
00502                 return QString();
00503         }
00504         int layoutCount = findLayout (layout);
00505         if (layoutCount < 0) {
00506                 excXKBLayoutUndefined (layout);
00507                 qError (errorString(),EXC_XKBLAYOUTUNDEFINED);
00508                 return QString();
00509         }
00510         int varCount = 0;
00511         QList<QString> vList = getXKBVariantList();
00512         QListIterator<QString> it (vList);
00513         for (; it.current();++it) {
00514                 if (varCount == layoutCount) {
00515                         return *it.current();
00516                 }
00517                 varCount++;
00518         }
00519         return QString();
00520 }
00521 
00522 //====================================
00523 // getXKBModel
00524 //------------------------------------
00525 QString SaXManipulateKeyboard::getXKBModel (void) {
00526         // .../
00529         // ----
00530         if (! mImport) {
00531                 return QString();
00532         }
00533         return mImport -> getItem ("XkbModel");
00534 }
00535 
00536 //====================================
00537 // findLayout
00538 //------------------------------------
00539 int SaXManipulateKeyboard::findLayout (const QString& layout) {
00540         // .../
00544         // ----
00545         int count  = 0;
00546         bool found = false;
00547         QString layoutData = mImport -> getItem ("XkbLayout");
00548         QStringList layouts = QStringList::split ( ",", layoutData );
00549         for (QStringList::Iterator it=layouts.begin(); it!=layouts.end();++ it) {
00550                 QString item (*it);
00551                 if (item == layout) {
00552                         found = true; break;
00553                 }
00554                 count++;
00555         }
00556         if (! found) {
00557                 return -1;
00558         }
00559         return count;
00560 }
00561 
00562 //====================================
00563 // transform string to Qlist
00564 //------------------------------------
00565 QList<QString> SaXManipulateKeyboard::createList ( const QString& data) {
00566         // .../
00569         // ----
00570         if (data.isEmpty()) {
00571                 return QList<QString>();
00572         }
00573         QList<QString> result; 
00574         QStringList dataList = QStringList::split ( ",", data, true );
00575         for (QStringList::Iterator it=dataList.begin(); it!=dataList.end();++ it) {
00576                 QString* item = new QString (*it);
00577                 result.append (item);
00578         }
00579         return result;
00580 }
00581 } // end namespace

Generated on Tue Nov 28 19:09:12 2006 for libsax by  doxygen 1.5.0