Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

keyboard.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include "keyboard.h"
00022 #include "configdlg.h"
00023 
00024 #include <qpe/global.h>
00025 #include <qpe/qcopenvelope_qws.h>
00026 
00027 #include <qwindowsystem_qws.h>
00028 #include <qpainter.h>
00029 #include <qfontmetrics.h>
00030 #include <qtimer.h>
00031 #include <qpe/qpeapplication.h>
00032 #include <qpe/config.h>
00033 #include <ctype.h>
00034 #include <qdir.h>
00035 #include <qtextstream.h>
00036 #include <qstringlist.h>
00037 
00038 #include <sys/utsname.h>
00039 
00040 using namespace MultiKey;
00041 
00042 static const char * const kb_config_xpm[] = {
00043 "13 7 2 1",
00044 "   c None",
00045 ".  c #000000",
00046 "             ",
00047 "      .      ",
00048 "     ...     ",
00049 "    .....    ",
00050 "      .      ",
00051 "      .      ",
00052 "             "};
00053 
00054 /* Keyboard::Keyboard {{{1 */
00055 Keyboard::Keyboard(QWidget* parent, const char* _name, WFlags f) :
00056     QFrame(parent, _name, f),  shift(0), lock(0), ctrl(0), alt(0), 
00057     meta(0), circumflex(0), diaeresis(0), baccent(0), accent(0),
00058     useLargeKeys(TRUE), usePicks(0), useRepeat(0), 
00059     pressedKeyRow(-1), pressedKeyCol(-1),
00060     unicode(-1), qkeycode(0), modifiers(0), schar(0), mchar(0), echar(0),
00061     configdlg(0)
00062 
00063 {
00064 
00065     // get the default font
00066     Config *config = new Config( "qpe" );
00067     config->setGroup( "Appearance" );
00068     QString familyStr = config->readEntry( "FontFamily", "smallsmooth" );
00069     int fontSize = config->readNumEntry( "FontSize", 10 );
00070     delete config;
00071 
00072     config = new Config("multikey");
00073     config->setGroup ("general");
00074     usePicks = config->readBoolEntry ("usePickboard", 0); // default closed
00075     useRepeat = config->readBoolEntry ("useRepeat", 1);
00076     delete config;
00077 
00078     setFont( QFont( familyStr, fontSize ) );
00079 
00080     picks = new KeyboardPicks( this );
00081     picks->setFont( QFont( familyStr, fontSize ) );
00082     picks->initialise();
00083     if (usePicks) {
00084 
00085         QObject::connect( picks, SIGNAL(key(ushort,ushort,ushort,bool,bool) ),
00086             this, SIGNAL(key(ushort,ushort,ushort,bool,bool)) );
00087 
00088     } else picks->hide();
00089 
00090     loadKeyboardColors();
00091 
00092     keys = new Keys();
00093 
00094     repeatTimer = new QTimer( this );
00095     connect( repeatTimer, SIGNAL(timeout()), this, SLOT(repeat()) );
00096 
00097     QCopChannel* kbdChannel = new QCopChannel("MultiKey/Keyboard", this);
00098     connect(kbdChannel, SIGNAL(received(const QCString&,const QByteArray&)),
00099             this, SLOT(receive(const QCString&,const QByteArray&)));
00100 }
00101 
00102 Keyboard::~Keyboard() {
00103 
00104     if ( configdlg ) { 
00105         delete configdlg;
00106         configdlg = 0;
00107     }
00108 
00109 }
00110 
00111 /* Keyboard::resizeEvent {{{1 */
00112 void Keyboard::resizeEvent(QResizeEvent*)
00113 {
00114     int ph = picks->sizeHint().height();
00115     picks->setGeometry( 0, 0, width(), ph );
00116     keyHeight = (height()-(usePicks ? ph : 0))/(keys->rows()?keys->rows():1);
00117 
00118     int nk; // number of keys?
00119     if ( useLargeKeys ) {
00120         nk = 15;
00121     } else {
00122         nk = 19;
00123     }
00124     defaultKeyWidth = (width()/nk)/2;
00125     xoffs = (width()-defaultKeyWidth*nk)/2; // empty key spaces?
00126 
00127 }
00128 
00129 /* KeyboardPicks::initialize {{{1 */
00130 void KeyboardPicks::initialise()
00131 {
00132     setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
00133     mode = 0;
00134     dc = new KeyboardConfig(this);
00135     configs.append(dc);
00136 }
00137 
00138 /* KeyboardPicks::sizeHint {{{1 */
00139 QSize KeyboardPicks::sizeHint() const
00140 {
00141     return QSize(240,fontMetrics().lineSpacing());
00142 }
00143 
00144 
00145 /* KeyboardConfig::generateText {{{1 */
00146 void KeyboardConfig::generateText(const QString &s)
00147 {
00148 #if defined(Q_WS_QWS) || defined(_WS_QWS_)
00149     for (int i=0; i<(int)backspaces; i++) {
00150         parent->emitKey( 0, ::Qt::Key_Backspace, 0, true, false );
00151         parent->emitKey( 0, ::Qt::Key_Backspace, 0, false, false );
00152     }
00153     for (int i=0; i<(int)s.length(); i++) {
00154         parent->emitKey( s[i].unicode(), 0, 0, true, false );
00155         parent->emitKey( s[i].unicode(), 0, 0, false, false );
00156     }
00157     parent->emitKey( 0, ::Qt::Key_Space, 0, true, false );
00158     parent->emitKey( 0, ::Qt::Key_Space, 0, false, false );
00159     backspaces = 0;
00160 #endif
00161 }
00162 
00163 
00164 
00165 
00166 /* Keyboard::paintEvent {{{1 */
00167 void Keyboard::paintEvent(QPaintEvent* e)
00168 {
00169     QPainter painter(this);
00170     painter.setClipRect(e->rect());
00171     drawKeyboard( painter );
00172     picks->dc->draw( &painter );
00173 }
00174 
00175 
00176 /* Keyboard::drawKeyboard {{{1 */
00177 
00178 void Keyboard::drawKeyboard(QPainter &p, int row, int col)
00179 {
00180 
00181 
00182     if (row != -1 && col != -1) { //just redraw one key
00183 
00184         int x = 0;
00185         for (int i = 0; i < col; i++) {
00186 
00187             x += keys->width(row, i) * defaultKeyWidth;
00188         }
00189         int y = (row - 1) * keyHeight + (usePicks ? picks->height() : 0);
00190 
00191         int keyWidth = keys->width(row, col);
00192 
00193         p.fillRect(x + 1, y + 1, 
00194                    keyWidth * defaultKeyWidth - 1, keyHeight - 1, 
00195                    pressed || keys->pressed(row, col) ? keycolor_pressed : keycolor);
00196 
00197         QImage *pix = keys->pix(row,col);
00198 
00199         ushort c = keys->uni(row, col);
00200 
00201         p.setPen(textcolor);
00202         if (!pix) {
00203             if ((shift || lock) && keys->shift(c)) 
00204 
00205                 if (circumflex && keys->circumflex(keys->shift(c)))
00206                     c = keys->circumflex(keys->shift(c));
00207                 else if (diaeresis && keys->diaeresis(keys->shift(c)))
00208                     c = keys->diaeresis(keys->shift(c));
00209                          else if (baccent && keys->baccent(keys->shift(c)))
00210                     c = keys->baccent(keys->shift(c));
00211                 else if (accent && keys->accent(keys->shift(c)))
00212                     c = keys->accent(keys->shift(c));
00213                 else if (meta && keys->meta(keys->shift(c)))
00214                     c = keys->meta(keys->shift(c));
00215                 else 
00216                     c = keys->shift(c);
00217 
00218             else if (meta && keys->meta(c)) 
00219                 c = keys->meta(c);
00220             else if (circumflex && keys->circumflex(c)) 
00221                 c = keys->circumflex(c);
00222                   else if (baccent && keys->baccent(c))
00223                 c = keys->baccent(c);
00224                   else if (accent && keys->accent(c))
00225                 c = keys->accent(c);
00226             else if (diaeresis && (keys->diaeresis(c) || c == 0x2c6)) {
00227 
00228                 // the diaeresis key itself has to be in the diaeresisMap,
00229                 // or just do this to make it display the diaeresis char.
00230                 
00231                 if (c == 0x2c6)
00232                     c = 0xa8;
00233                 else 
00234                     c = keys->diaeresis(c);
00235             }
00236             
00237             p.drawText(x, y, 
00238                defaultKeyWidth * keyWidth + 3, keyHeight,
00239                AlignCenter, (QChar)c);
00240         }
00241         else
00242             // center the image in the middle of the key
00243             p.drawImage( x + (defaultKeyWidth * keyWidth - pix->width())/2 + 1, 
00244                           y + (keyHeight - pix->height())/2 + 1, 
00245                           *pix );
00246 
00247         // this fixes the problem that the very right end of the board's vertical line
00248         // gets painted over, because it's one pixel shorter than all other keys
00249         p.setPen(keycolor_lines);
00250         p.drawLine(width() - 1, 0, width() - 1, height());
00251 
00252     } else {
00253 
00254 
00255     p.fillRect(0, 0, width(), height(), keycolor);
00256 
00257     for (row = 1; row <= keys->rows(); row++) {
00258 
00259         int x = 0;
00260         int y = (row - 1) * keyHeight + (usePicks ? picks->height() : 0);
00261 
00262         p.setPen(keycolor_lines);
00263         p.drawLine(x, y, x + width(), y);
00264 
00265         for (int col = 0; col < keys->numKeys(row); col++) {
00266 
00267             QImage *pix = keys->pix(row, col);
00268             int keyWidth = keys->width(row, col);
00269 
00270 
00271             int keyWidthPix = defaultKeyWidth * keyWidth;
00272 
00273             if (keys->pressed(row, col)) 
00274                 p.fillRect(x+1, y+1, keyWidthPix - 1, 
00275                            keyHeight - 1, keycolor_pressed);
00276 
00277             ushort c = keys->uni(row, col);
00278 
00279             p.setPen(textcolor);
00280             if (!pix) {
00281                 if ((shift || lock) && keys->shift(c)) 
00282 
00283                     if (circumflex && keys->circumflex(keys->shift(c)))
00284                         c = keys->circumflex(keys->shift(c));
00285                     else if (diaeresis && keys->diaeresis(keys->shift(c)))
00286                         c = keys->diaeresis(keys->shift(c));
00287                     else if (baccent && keys->baccent(keys->shift(c)))
00288                         c = keys->baccent(keys->shift(c));
00289                     else if (accent && keys->accent(keys->shift(c)))
00290                         c = keys->accent(keys->shift(c));
00291                     else if (meta && keys->meta(keys->shift(c)))
00292                         c = keys->meta(keys->shift(c));
00293                     else 
00294                         c = keys->shift(c);
00295 
00296                 else if (meta && keys->meta(c)) 
00297                     c = keys->meta(c);
00298                 else if (circumflex && keys->circumflex(c))
00299                     c = keys->circumflex(c);
00300                 else if (baccent && keys->baccent(c))
00301                     c = keys->baccent(c);
00302                 else if (accent && keys->accent(c))
00303                     c = keys->accent(c);
00304                 else if (diaeresis && (keys->diaeresis(c) || c == 0x2c6)) {
00305 
00306                     if (c == 0x2c6)
00307                         c = 0xa8;
00308                     else 
00309                         c = keys->diaeresis(c);
00310                 }
00311 
00312                 p.drawText(x, y, 
00313                    keyWidthPix + 3, keyHeight,
00314                    AlignCenter, (QChar)c);
00315             }
00316             else {
00317                 // center the image in the middle of the key
00318                 pix->setColor(1, textcolor.rgb());
00319                 p.drawImage( x + (keyWidthPix - pix->width())/2 + 1, 
00320                               y + (keyHeight - pix->height())/2 + 1, 
00321                               QImage(*pix) );
00322             }
00323 
00324             p.setPen(keycolor_lines);
00325             p.drawLine(x, y, x, y + keyHeight);
00326 
00327             x += keyWidthPix;
00328         }
00329 
00330 
00331     }
00332     p.setPen(keycolor_lines);
00333     p.drawLine(0, height() - 1, width(), height() - 1);
00334     p.drawLine(width() - 1, 0, width() - 1, height());
00335     }
00336 
00337 }
00338 
00339 
00340 /* Keyboard::mousePressEvent {{{1 */
00341 void Keyboard::mousePressEvent(QMouseEvent *e)
00342 {
00343     int row = (e->y() - (usePicks ? picks->height() : 0)) / keyHeight + 1;
00344     if (row > 5) row = 5;
00345 
00346     // figure out the column
00347     int col = 0; 
00348     for (int w = 0; e->x() >= w; col++)
00349         if (col < keys->numKeys(row)) // it segfaults if it trys to read past numKeys
00350             w += keys->width(row,col) * defaultKeyWidth;
00351         else break;
00352 
00353     if (col <= 0) return;
00354 
00355     col --; // rewind one...
00356 
00357     qkeycode = keys->qcode(row, col);
00358     unicode = keys->uni(row, col);
00359 
00360     // might need to repaint if two or more of the same keys.
00361     // should be faster if just paint one key even though multiple keys exist.
00362     bool need_repaint = FALSE; 
00363 
00364     // circumflex and diaeresis support
00365     // messy to have this here, but too hard to implement any other method
00366     if (unicode == 0x2c6) { 
00367 
00368         unicode = 0; 
00369         if (shift || lock) {
00370 
00371             // diaeresis
00372             qkeycode = 0x2001; 
00373         }
00374         else {
00375             
00376             // circumflex
00377             qkeycode = 0x2000; 
00378         }
00379     }
00380 
00381     // Back accent character support
00382 
00383     // the keys from 2c6 ~ 2cf should be used instead of the ascii one
00384     if (unicode == 0x2cb) {
00385 
00386         unicode = 0;
00387         if (shift || lock) {
00388 
00389             // circumblex
00390             qkeycode = 0x2000;
00391         }
00392         else {
00393 
00394             // back accent
00395             qkeycode = 0x2002;
00396         }
00397     }
00398 
00399     // Accent character support
00400 
00401     if (unicode == 0x2ca) {
00402 
00403         unicode = 0;
00404         if (shift || lock) {
00405 
00406             // diaeresis
00407             qkeycode = 0x2001;
00408         }
00409         else {
00410 
00411             // accent
00412             qkeycode = 0x2003;
00413         }
00414     }
00415 
00416 
00417     if (unicode == 0) { // either Qt char, or nothing
00418 
00419         if (qkeycode == Qt::Key_F1) { // toggle the pickboard
00420 
00421             if ( configdlg ) { 
00422 
00423                 delete configdlg; 
00424                 configdlg = 0;
00425             }
00426             else {
00427                configdlg = new ConfigDlg ();
00428                connect(configdlg, SIGNAL(setMapToDefault()), 
00429                        this, SLOT(setMapToDefault()));
00430                connect(configdlg, SIGNAL(setMapToFile(QString)), 
00431                        this, SLOT(setMapToFile(QString)));
00432                connect(configdlg, SIGNAL(pickboardToggled(bool)), 
00433                        this, SLOT(togglePickboard(bool)));
00434                connect(configdlg, SIGNAL(repeatToggled(bool)),
00435                        this, SLOT(toggleRepeat(bool)));
00436                connect(configdlg, SIGNAL(reloadKeyboard()),
00437                        this, SLOT(reloadKeyboard()));
00438                connect(configdlg, SIGNAL(configDlgClosed()),
00439                        this, SLOT(cleanupConfigDlg()));
00440                connect(configdlg, SIGNAL(reloadSw()),
00441                        this, SLOT(reloadSw()));
00442                configdlg->showMaximized();
00443                configdlg->show();
00444                configdlg->raise();
00445             }
00446 
00447         } else if (qkeycode == Qt::Key_Control) {
00448             need_repaint = TRUE;
00449 
00450             if (ctrl) {
00451 
00452                 *ctrl = 0;
00453                 ctrl = 0;
00454 
00455             } else {
00456 
00457                 ctrl = keys->pressedPtr(row, col);
00458                 need_repaint = TRUE;
00459                 *ctrl = !keys->pressed(row, col);
00460 
00461             }
00462 
00463         } else if (qkeycode == Qt::Key_Alt) {
00464             need_repaint = TRUE;
00465 
00466             if (alt) {
00467                 *alt = 0;
00468                 alt = 0;
00469 
00470             } else {
00471 
00472                 alt = keys->pressedPtr(row, col);
00473                 need_repaint = TRUE;
00474                 *alt = !keys->pressed(row, col);
00475             }
00476 
00477         } else if (qkeycode == Qt::Key_Shift) {
00478             need_repaint = TRUE;
00479 
00480             if (shift) {
00481                 *shift = 0;
00482                 shift = 0;
00483             }
00484             else {
00485                 shift = keys->pressedPtr(row, col);
00486                 *shift = 1;
00487                 if (lock) {
00488                     *lock = 0;
00489                     lock = 0;
00490                 }
00491             }
00492 
00493 
00494             /* 
00495              * want to be able to hit circumflex/diaeresis -> shift
00496              * to type in shifted circumflex/diaeresis chars.
00497              * same thing with meta
00498 
00499             if (meta) { *meta = 0; meta = 0; }
00500             if (circumflex) { *circumflex = 0; circumflex = 0; }
00501             if (diaeresis) { *diaeresis = 0; diaeresis = 0; }
00502 
00503              */
00504 
00505         } else if (qkeycode == Qt::Key_CapsLock) {
00506             need_repaint = TRUE;
00507 
00508             if (lock) {
00509                 *lock = 0;
00510                 lock = 0;
00511             }
00512             else {
00513                 lock = keys->pressedPtr(row, col);;
00514                 *lock = true;;
00515                 if (shift) {
00516                     *shift = 0;
00517                     shift = 0;
00518                 }
00519             }
00520 
00521             /*
00522             if (meta) { *meta = 0; meta = 0; }
00523             if (circumflex) { *circumflex = 0; circumflex = 0; }
00524             if (diaeresis) { *diaeresis = 0; diaeresis = 0; }
00525             */
00526 
00527         } else if (qkeycode == Qt::Key_Meta) {
00528             need_repaint = TRUE;
00529 
00530             if (meta) {
00531                 *meta = 0;
00532                 meta = 0;
00533 
00534             } else {
00535 
00536                 meta = keys->pressedPtr(row, col);
00537                 *meta = true;
00538             }
00539 
00540             // reset all the other keys
00541             if (shift) { *shift = 0; shift = 0; } 
00542             if (lock) { *lock = 0; lock = 0; }
00543             if (circumflex) { *circumflex = 0; circumflex = 0; }
00544             if (diaeresis) { *diaeresis = 0; diaeresis = 0; }
00545                 if (baccent) { *baccent = 0; baccent = 0; }
00546                 if (accent) { *accent = 0; accent = 0; }
00547 
00548             // dont need to emit this key... acts same as alt
00549             qkeycode = 0;
00550 
00551         // circumflex
00552         } else if (qkeycode == 0x2000) {
00553             need_repaint = TRUE;
00554 
00555             if (circumflex) {
00556 
00557                 *circumflex = 0;
00558                 circumflex = 0;
00559 
00560             } else {
00561 
00562                 circumflex = keys->pressedPtr(row, col);
00563                 *circumflex = true;
00564             }
00565 
00566             /* no need to turn off shift or lock if circumflex
00567              * keys are pressed
00568              
00569             if (shift) { *shift = 0; shift = 0; }
00570             if (lock) { *lock = 0; lock = 0; }
00571 
00572              */
00573             
00574             // have to reset all the other keys
00575             if (meta) { *meta = 0; meta = 0; }
00576             if (diaeresis) { 
00577                 
00578                 // *diaeresis and *circumflex point to the same thing
00579                 // when diaeresis is enabled and you hit the circumflex
00580                 // since they are the same key, it should turn off the
00581                 // key
00582                 
00583                 *diaeresis = 0; 
00584                 diaeresis = 0; 
00585                 circumflex = 0;
00586             }
00587 
00588             qkeycode = 0;
00589 
00590         // diaeresis
00591         } else if (qkeycode == 0x2001) {
00592             need_repaint = TRUE;
00593 
00594             if (diaeresis) {
00595 
00596                 *diaeresis = 0;
00597                 diaeresis = 0;
00598 
00599             } else {
00600 
00601                 diaeresis = keys->pressedPtr(row, col);
00602                 *diaeresis = true;
00603             }
00604 
00605              
00606             if (shift) { *shift = 0; shift = 0; }
00607 
00608             /*
00609              *
00610             if (lock) { *lock = 0; lock = 0; }
00611              *
00612              */
00613 
00614             if (meta) { *meta = 0; meta = 0; }
00615             if (circumflex) { 
00616 
00617                 // *circumflex = 0; 
00618                 //
00619                 // same thing the diaeresis pointer points too
00620                 
00621                 circumflex = 0; 
00622             }
00623 
00624 
00625             qkeycode = 0;
00626 
00627         // Back accent
00628         } else if (qkeycode == 0x2002) {
00629             need_repaint = TRUE;
00630 
00631             if (baccent) {
00632 
00633                 *baccent = 0;
00634                 baccent = 0;
00635 
00636             } else {
00637 
00638                 baccent = keys->pressedPtr(row, col);
00639                 *baccent = true;
00640             }
00641 
00642 
00643             if (shift) { *shift = 0; shift = 0; }
00644             if (meta) { *meta = 0; meta = 0; }
00645                     if (accent) { *accent = 0; accent = 0; }
00646 
00647             qkeycode = 0;
00648         
00649            // Accent
00650         } else if (qkeycode == 0x2003) {
00651             need_repaint = TRUE;
00652 
00653             if (accent) {
00654 
00655                 *accent = 0;
00656                 accent = 0;
00657 
00658             } else {
00659 
00660                 accent = keys->pressedPtr(row, col);
00661                 *accent = true;
00662             }
00663 
00664 
00665             if (shift) { *shift = 0; shift = 0; }
00666             if (meta) { *meta = 0; meta = 0; }
00667                     if (baccent) { *baccent = 0; }
00668 
00669             qkeycode = 0;
00670         }
00671 
00672     }
00673     else { // normal char
00674         if ((shift || lock) && keys->shift(unicode)) {
00675 
00676             // make diaeresis/circumflex -> shift input shifted
00677             // diaeresis/circumflex chars
00678             
00679             if (circumflex && keys->circumflex(keys->shift(unicode)))
00680                 unicode = keys->circumflex(keys->shift(unicode));
00681             else if (diaeresis && keys->diaeresis(keys->shift(unicode)))
00682                 unicode = keys->diaeresis(keys->shift(unicode));
00683                 else if (baccent && keys->baccent(keys->shift(unicode)))
00684                 unicode = keys->baccent(keys->shift(unicode));
00685             else if (accent && keys->accent(keys->shift(unicode)))
00686                 unicode = keys->accent(keys->shift(unicode));
00687             else if (meta && keys->meta(keys->shift(unicode)))
00688                 unicode = keys->meta(keys->shift(unicode));
00689             else
00690                 unicode = keys->shift(unicode);
00691         }
00692         else if (meta && keys->meta(unicode)) {
00693             unicode = keys->meta(unicode);
00694         }
00695         else if (circumflex && keys->circumflex(unicode)) {
00696             unicode = keys->circumflex(unicode);
00697         }
00698         else if (diaeresis && keys->diaeresis(unicode)) {
00699 
00700             unicode = keys->diaeresis(unicode);
00701         }
00702            else if (baccent && keys->baccent(unicode)) {
00703             unicode = keys->baccent(unicode);
00704         }
00705         else if (accent && keys->accent(unicode)) {
00706             unicode = keys->accent(unicode);
00707         }
00708     }
00709 
00710     // korean parsing
00711     if (keys->lang == "ko") {
00712 
00713         unicode = parseKoreanInput(unicode);
00714     }
00715 
00716     modifiers = (ctrl ? Qt::ControlButton : 0) | (alt ? Qt::AltButton : 0);
00717 
00718     if ('A' <= unicode && unicode <= 'z' && modifiers) {
00719 
00720         qkeycode = QChar(unicode).upper();
00721         unicode = qkeycode - '@';
00722     }
00723 
00724     QWSServer::sendKeyEvent(unicode, qkeycode, modifiers, true, false); 
00725 
00726     // pickboard stuff
00727     if (usePicks) {
00728 
00729         KeyboardConfig *dc = picks->dc;
00730     
00731         if (dc) {
00732             if (qkeycode == Qt::Key_Backspace) {
00733                 dc->input.remove(dc->input.last()); // remove last input
00734                 dc->decBackspaces();
00735             } else if ( qkeycode == Qt::Key_Return || QChar(unicode).isPunct() || QChar(unicode).isSpace() || unicode == 0) {
00736                 dc->input.clear();
00737                 dc->resetBackspaces();
00738             } else {
00739                 dc->add(QString(QChar(unicode)));
00740                 dc->incBackspaces();
00741             }
00742         }
00743         picks->repaint();
00744     }
00745 
00746 
00747     // painting
00748     pressed = TRUE;
00749 
00750     pressedKeyRow = row;
00751     pressedKeyCol = col;
00752 
00753     if (need_repaint) repaint(FALSE);
00754     else { // just paint the one key pressed
00755 
00756 
00757 
00758         QPainter p(this);
00759         drawKeyboard(p, row, col);
00760 
00761     }
00762 
00763     if (useRepeat) repeatTimer->start( 800 );
00764     //pressTid = startTimer(80);
00765 
00766 }
00767 
00768 void Keyboard::receive(const QCString &msg, const QByteArray &data)
00769 {
00770     if (msg == "setmultikey(QString)") {
00771         QDataStream stream(data, IO_ReadOnly);
00772         QString map;
00773         stream >> map;
00774         setMapToFile(map);
00775     } else if (msg == "getmultikey()") {
00776         reloadSw();
00777     }
00778 }
00779 
00780 /* Keyboard::mouseReleaseEvent {{{1 */
00781 void Keyboard::mouseReleaseEvent(QMouseEvent*)
00782 {
00783     pressed = FALSE;
00784     //if ( pressTid == 0 )
00785 #if defined(Q_WS_QWS) || defined(_WS_QWS_)
00786     if ( unicode != -1 ) {
00787         emit key( unicode, qkeycode, modifiers, false, false );
00788         repeatTimer->stop();
00789     }
00790 #endif
00791     if (shift && unicode != 0) {
00792 
00793 
00794         *shift = 0; // unpress shift key
00795         shift = 0;  // reset the shift pointer
00796         repaint(FALSE);
00797 
00798     } 
00799     if (ctrl && unicode != 0) {
00800 
00801         *ctrl = 0;
00802         ctrl = 0;
00803         repaint(FALSE);
00804 
00805     }
00806     if (alt && alt != 0) {
00807 
00808         *alt = 0;
00809         alt = 0;
00810         repaint(FALSE);
00811 
00812     }
00813     
00814     /*
00815      * do not make the meta key release after being pressed
00816      *
00817 
00818     else if (meta && unicode != 0) {
00819 
00820         *meta = 0;
00821         meta = 0;
00822         repaint(FALSE);
00823     }
00824 
00825      */
00826 
00827     else clearHighlight();
00828 }
00829 
00830 /* Keyboard::timerEvent {{{1 */
00831 
00832 /* dont know what this does, but i think it is here so that if your screen
00833  * sticks (like on an ipaq) then it will stop repeating if you click another
00834  * key... but who knows what anything does in this thing anyway?
00835 
00836  void Keyboard::timerEvent(QTimerEvent* e)
00837 {
00838     if ( e->timerId() == pressTid ) {
00839         killTimer(pressTid);
00840         pressTid = 0;
00841         if ( !pressed )
00842         cout << "calling clearHighlight from timerEvent\n";
00843             //clearHighlight();
00844     }
00845 }
00846 */
00847 
00848 void Keyboard::repeat()
00849 {
00850 
00851   repeatTimer->start( 200 );
00852   emit key( unicode, qkeycode, modifiers, true, true );
00853 }
00854 
00855 void Keyboard::clearHighlight()
00856 {
00857     if ( pressedKeyRow >= 0 && pressedKeyCol >= 0) {
00858             int tmpRow = pressedKeyRow;
00859         int tmpCol = pressedKeyCol;
00860 
00861             pressedKeyRow = -1;
00862             pressedKeyCol = -1;
00863 
00864             QPainter p(this);
00865             drawKeyboard(p, tmpRow, tmpCol);
00866     }
00867 }
00868 
00869 
00870 /* Keyboard::sizeHint {{{1 */
00871 QSize Keyboard::sizeHint() const
00872 {
00873     QFontMetrics fm=fontMetrics();
00874     int keyHeight = fm.lineSpacing() + 2;
00875 
00876     return QSize( 240, keyHeight * keys->rows() + (usePicks ? picks->sizeHint().height() : 0) + 1);
00877 }
00878 
00879 
00880 void Keyboard::resetState()
00881 {
00882     if (shift) { *shift = 0; shift = 0; }
00883     if (lock)  {*lock = 0;  lock = 0; }
00884     if (meta)  { *meta = 0;  meta = 0; }
00885     if (circumflex) { *circumflex = 0; circumflex = 0; }
00886     if (diaeresis)  { *diaeresis = 0; diaeresis = 0; }
00887     if (baccent)  { *baccent = 0; baccent = 0; }
00888     if (accent)  { *accent = 0; accent = 0; }
00889 
00890     schar = mchar = echar = 0;
00891     picks->resetState();
00892 }
00893 
00894 /* Keyboard::togglePickboard {{{1 */
00895 void Keyboard::togglePickboard(bool on_off)
00896 {
00897     usePicks = on_off;
00898     if (usePicks) {
00899         picks->show();
00900         //move(x(), y() - picks->height()); // not required anymore because QCopChannel::send
00901         //adjustSize();
00902         QObject::connect( picks, SIGNAL(key(ushort,ushort,ushort,bool,bool) ),
00903             this, SIGNAL(key(ushort,ushort,ushort,bool,bool)) );
00904     } else {
00905 
00906         picks->hide();
00907         picks->resetState();
00908         //move(x(), y() + picks->height());
00909         //adjustSize();
00910         QObject::disconnect( picks, SIGNAL(key(ushort,ushort,ushort,bool,bool) ),
00911             this, SIGNAL(key(ushort,ushort,ushort,bool,bool)) );
00912 
00913     }
00914     /*
00915      * this closes && opens the input method
00916      */
00917     QCopChannel::send ("QPE/TaskBar", "hideInputMethod()");
00918     QCopChannel::send ("QPE/TaskBar", "showInputMethod()");
00919 }
00920 
00921 void Keyboard::toggleRepeat(bool on) {
00922 
00923     useRepeat = on;
00924     //cout << "setting useRepeat to: " << useRepeat << "\n";
00925 }
00926 
00927 void Keyboard::cleanupConfigDlg() {
00928 
00929     if ( configdlg ) { 
00930         delete configdlg; 
00931         configdlg = 0;
00932     }
00933 }
00934 
00935 void Keyboard::reloadSw() {
00936     QCopEnvelope e("MultiKey/Switcher", "setsw(QString,QString)");
00937 
00938     Config* config = new Config("multikey");
00939     config->setGroup("keymaps");
00940     QString current_map = config->readEntry("current", "en.keymap");
00941     delete config;
00942 
00943     e << ConfigDlg::loadSw().join("|") << current_map;
00944 }
00945 
00946 /* Keyboard::setMapTo ... {{{1 */
00947 void Keyboard::setMapToDefault() {
00948 
00949 
00950     /* load current locale language map */
00951     Config *config = new Config("locale");
00952     config->setGroup( "Language" );
00953     QString l = config->readEntry( "Language" , "en" );
00954     delete config;
00955 
00956     /* if Language represents as en_US, ru_RU, etc... */
00957     int d = l.find('_');
00958     if (d != -1) {
00959         l.remove(d, l.length()-d);
00960     }
00961     QString key_map = QPEApplication::qpeDir() + "share/multikey/" 
00962             + l + ".keymap";
00963 
00964     /* save change to multikey config file */
00965     config = new Config("multikey");
00966     config->setGroup ("keymaps");
00967     config->writeEntry ("current", key_map); // default closed
00968     delete config;
00969 
00970     int prevRows = keys->rows();
00971 
00972     delete keys;
00973     keys = new Keys(key_map);
00974 
00975     // have to repaint the keyboard
00976     if (prevRows != keys->rows()) {
00977 
00978         QCopChannel::send ("QPE/TaskBar", "hideInputMethod()"); 
00979         QCopChannel::send ("QPE/TaskBar", "showInputMethod()");
00980 
00981     } else repaint(FALSE);
00982 
00983     resetState();
00984 }
00985 
00986 void Keyboard::setMapToFile(QString map) {
00987 
00988     /* save change to multikey config file */
00989     Config *config = new Config("multikey");
00990     config->setGroup ("keymaps");
00991     config->writeEntry ("current", map); // default closed
00992 
00993     delete config;
00994 
00995     int prevRows = keys->rows();
00996 
00997     delete keys;
00998     if (QFile(map).exists()) 
00999         keys = new Keys(map);
01000     else 
01001         keys = new Keys();
01002 
01003     if (keys->rows() != prevRows) {
01004 
01005         QCopChannel::send ("QPE/TaskBar", "hideInputMethod()");
01006         QCopChannel::send ("QPE/TaskBar", "showInputMethod()");
01007     }
01008     else repaint(FALSE);
01009 
01010     resetState();
01011 }
01012 
01013 /* Keybaord::reloadKeyboard {{{1 */
01014 void Keyboard::reloadKeyboard() {
01015 
01016     // reload colors and redraw
01017     loadKeyboardColors();
01018     repaint();
01019 
01020 }
01021 
01022 void Keyboard::loadKeyboardColors() {
01023 
01024     Config config ("multikey");
01025     config.setGroup("colors");
01026 
01027     QStringList color;
01028     color = config.readListEntry("keycolor", QChar(','));
01029     if (color.isEmpty()) {
01030         color = QStringList::split(",", "240,240,240");
01031         config.writeEntry("keycolor", color.join(","));
01032 
01033     }
01034     keycolor = QColor(color[0].toInt(), color[1].toInt(), color[2].toInt());
01035 
01036     color = config.readListEntry("keycolor_pressed", QChar(','));
01037     if (color.isEmpty()) {
01038         color = QStringList::split(",", "171,183,198");
01039         config.writeEntry("keycolor_pressed", color.join(","));
01040 
01041     }
01042     keycolor_pressed = QColor(color[0].toInt(), color[1].toInt(), color[2].toInt());
01043 
01044     color = config.readListEntry("keycolor_lines", QChar(','));
01045     if (color.isEmpty()) {
01046         color = QStringList::split(",", "138,148,160");
01047         config.writeEntry("keycolor_lines", color.join(","));
01048 
01049     }
01050     keycolor_lines = QColor(color[0].toInt(), color[1].toInt(), color[2].toInt());
01051 
01052     color = config.readListEntry("textcolor", QChar(','));
01053     if (color.isEmpty()) {
01054         color = QStringList::split(",", "43,54,68");
01055         config.writeEntry("textcolor", color.join(","));
01056 
01057     }
01058     textcolor = QColor(color[0].toInt(), color[1].toInt(), color[2].toInt());
01059 
01060 }
01061 
01062 /* korean input functions {{{1 
01063  *
01064  * TODO
01065  * one major problem with this implementation is that you can't move the
01066  * cursor after inputing korean chars, otherwise it will eat up and replace
01067  * the char before the cursor you move to. fix that
01068  *
01069  * make backspace delete one single char, not the whole thing if still 
01070  * editing.
01071  *
01072  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
01073  *
01074  * how korean input works
01075  *
01076  * all following chars means unicode char value and are in hex
01077  *
01078  * 초음 = schar (start char)
01079  * 중음 = mchar (middle char)
01080  * 끝음 = echar (end char)
01081  *
01082  * there are 19 schars. unicode position is at 1100 - 1112
01083  * there are 21 mchars. unicode position is at 1161 - 1175
01084  * there are 27 echars. unicode position is at 11a8 - 11c2
01085  *
01086  * the map with everything combined is at ac00 - d7a3
01087  *
01088  */
01089 
01090 ushort Keyboard::parseKoreanInput (ushort c) {
01091 
01092         if ((c != 0 && (c < 0x1100 || 0x11c2 < c) && (c < 0xac00 || 0xd7a3 < c)) 
01093           ||
01094         (c == 0 && qkeycode != Qt::Key_Shift && Qt::Key_CapsLock != qkeycode
01095          && qkeycode != Qt::Key_Control && qkeycode != Qt::Key_Alt)) {
01096 
01097                 schar = 0, mchar = 0, echar = 0;
01098         return c;
01099         }
01100 
01101         if ( 0x1100 <= c && c <= 0x1112 ) { // schar or echar was input
01102 
01103                 if (schar == 0 || (schar != 0 && mchar == 0)) {
01104                         schar = c; mchar = 0; echar = 0;
01105                         return c;
01106                 }
01107                 else if (mchar != 0) {
01108 
01109                         if (echar == 0) {
01110 
01111                                 if (!(echar = constoe(c))) {
01112 
01113                                         schar = c; mchar = 0; echar = 0; 
01114                                         return c;
01115                                 }
01116 
01117                         }
01118                         else { // must figure out what the echar is
01119 
01120                                 if (echar == 0x11a8) { // ㄱ
01121 
01122                                         if (c == 0x1100)                echar = 0x11a9; // ㄱ + ㄱ
01123                                         else if (c == 0x1109)   echar = 0x11aa; // ㄱ + ㅅ
01124                                         else { 
01125                                                 schar = c; mchar = 0; echar = 0; 
01126                                                 return c;
01127                                         }
01128 
01129                                 } else if (echar == 0x11ab) { // ㄴ
01130 
01131                                         if (c == 0x110c)                echar = 0x11ac; // ㄴ + ㅈ
01132                                         else if (c == 0x1112)   echar = 0x11ad; // ㄴ + ㅎ
01133                                         else {
01134                                                 schar = c; mchar = 0; echar = 0; 
01135                                                 return c;
01136                                         }
01137 
01138                                 } else if (echar == 0x11af) { // ㄹ
01139 
01140                                         if (c == 0x1100)                echar = 0x11b0; // ㄹ + ㄱ
01141                                         else if (c == 0x1106)   echar = 0x11b1; // ㄹ + ㅁ
01142                                         else if (c == 0x1107)   echar = 0x11b2; // ㄹ + ㅂ
01143                                         else if (c == 0x1109)   echar = 0x11b3; // ㄹ + ㅅ
01144                                         else if (c == 0x1110)   echar = 0x11b4; // ㄹ + ㅌ
01145                                         else if (c == 0x1111)   echar = 0x11b5; // ㄹ + ㅍ
01146                                         else if (c == 0x1112)   echar = 0x11b6; // ㄹ + ㅎ
01147                                         else {
01148                                                 schar = c; mchar = 0; echar = 0; 
01149                                                 return c;
01150                                         }
01151 
01152                                 } else if (echar == 0x11b8) { // ㅂ
01153 
01154                                         if (c == 0x1109)                echar = 0x11b9; // ㅂ + ㅅ
01155                                         else {
01156                                                 schar = c; mchar = 0; echar = 0; 
01157                                                 return c;
01158                                         }
01159 
01160                                 } else if (echar == 0x11ba) { // ㅅ 
01161 
01162                                         if (c == 0x1109)                echar = 0x11bb; // ㅅ + ㅅ 
01163                                         else {
01164                                                 schar = c; mchar = 0; echar = 0; 
01165                                                 return c;
01166                                         }
01167 
01168                                 } else { // if any other char, cannot combine chars
01169 
01170                                         schar = c; mchar = 0; echar = 0;
01171                                         return c;
01172                                 }
01173 
01174                                 unicode = echar;
01175                         }
01176                 }
01177 
01178         }
01179         else if (0x1161 <= c && c <= 0x1175) { // mchar was input
01180 
01181                 if (schar != 0 && mchar == 0) { mchar = c; }
01182 
01183                 else if (schar != 0 && mchar != 0 && echar == 0) {
01184 
01185                         switch (mchar) {
01186                                 case 0x1169:
01187                                         if (c == 0x1161) mchar = 0x116a;
01188                                         else if (c == 0x1162) mchar = 0x116b;
01189                                         else if (c == 0x1175) mchar = 0x116c;
01190                                         else {
01191                                                 schar = 0; mchar = 0; echar = 0;
01192                                                 return c;
01193                                         }
01194                                         break;
01195                                 case 0x116e:
01196                                         if (c == 0x1165) mchar = 0x116f;
01197                                         else if (c == 0x1166) mchar = 0x1170;
01198                                         else if (c == 0x1175) mchar = 0x1171;
01199                                         else {
01200                                                 schar = 0; mchar = 0; echar = 0;
01201                                                 return c;
01202                                         }
01203                                         break;
01204                                 case 0x1173:
01205                                         if (c == 0x1175) mchar = 0x1174;
01206                                         else {
01207                                                 schar = 0; mchar = 0; echar = 0;
01208                                                 return c;
01209                                         }
01210                                         break;
01211                                 default: 
01212                                         schar = 0; mchar = 0; echar = 0;
01213                                         return c;
01214                         }
01215                 }
01216                 else if (schar != 0 && mchar != 0 && echar != 0) {
01217 
01218                         emit key( 8, Qt::Key_Backspace, 0, true, false );
01219 
01220                         ushort prev = 0;
01221                         switch (echar) {
01222                                 /*
01223                                 case 0x11a9:
01224                                         prev = combineKoreanChars(schar, mchar, 0x11a8);
01225                                         schar = 0x1100; 
01226                                         break;
01227                                 */
01228                                 case 0x11aa:
01229                                         prev = combineKoreanChars(schar, mchar, 0x11a8);
01230                                         schar = 0x1109;
01231                                         break;
01232                                 case 0x11ac:
01233                                         prev = combineKoreanChars(schar, mchar, 0x11ab);
01234                                         schar = 0x110c; 
01235                                         break;
01236                                 case 0x11ad:
01237                                         prev = combineKoreanChars(schar, mchar, 0x11ab);
01238                                         schar = 0x1112;
01239                                         break;
01240                                 case 0x11b0:
01241                                         prev = combineKoreanChars(schar, mchar, 0x11af);
01242                                         schar = 0x1100; 
01243                                         break;
01244                                 case 0x11b1:
01245                                         prev = combineKoreanChars(schar, mchar, 0x11af);
01246                                         schar = 0x1106;
01247                                         break;
01248                                 case 0x11b2:
01249                                         prev = combineKoreanChars(schar, mchar, 0x11af);
01250                                         schar = 0x1107; 
01251                                         break;
01252                                 case 0x11b3:
01253                                         prev = combineKoreanChars(schar, mchar, 0x11af);
01254                                         schar = 0x1109;
01255                                         break;
01256                                 case 0x11b4:
01257                                         prev = combineKoreanChars(schar, mchar, 0x11af);
01258                                         schar = 0x1110;
01259                                         break;
01260                                 case 0x11b9:
01261                                         prev = combineKoreanChars(schar, mchar, 0x11b8);
01262                                         schar = 0x1109;
01263                                         break;
01264                                 /*
01265                                 case 0x11bb:
01266                                         prev = combineKoreanChars(schar, mchar, 0x11ba);
01267                                         schar = 0x1109; 
01268                                         break;
01269                                 */
01270                                 default: 
01271 
01272                                         if (constoe(echar)) {
01273 
01274                                                 prev = combineKoreanChars(schar, mchar, 0);
01275                                                 schar = constoe(echar); 
01276                                         } 
01277                                         break;
01278                         }
01279                         
01280                         emit key( prev, prev, 0, true, false );
01281 
01282                         mchar = c; echar = 0;
01283 
01284                         return combineKoreanChars(schar, mchar, 0);
01285                 
01286                 } 
01287                 else {
01288                         schar = 0; mchar = 0; echar = 0;
01289                         return c;
01290                 }
01291 
01292         } 
01293         else /*if (c == ' ')*/ return c;
01294 
01295 
01296         // and now... finally delete previous char, and return new char
01297         emit key( 8, Qt::Key_Backspace, 0, true, false );
01298 
01299 
01300         return combineKoreanChars( schar, mchar, echar);
01301 
01302 }
01303 
01304 ushort Keyboard::combineKoreanChars(const ushort s, const ushort m, const ushort e) {
01305 
01306         return ((s - 0x1100) * 588) + ((m - 0x1161) * 28) + (e ? e - 0x11a7 : 0) + 0xac00;
01307 
01308 }
01309 
01310 ushort Keyboard::constoe(const ushort c) {
01311 
01312         // converts schars to echars if possible
01313 
01314         if (0x1100 <= c && c <= 0x1112) { // schar to echar
01315 
01316                 switch (c) {
01317                         case 0x1100: return 0x11a8;
01318                         case 0x1101: return 0x11a9;
01319                         case 0x1102: return 0x11ab;
01320                         case 0x1103: return 0x11ae;
01321                         case 0x1105: return 0x11af;
01322                         case 0x1106: return 0x11b7;
01323                         case 0x1107: return 0x11b8;
01324                         case 0x1109: return 0x11ba;
01325                         case 0x110a: return 0x11bb;
01326                         case 0x110b: return 0x11bc;
01327                         case 0x110c: return 0x11bd;
01328                         case 0x110e: return 0x11be;
01329                         case 0x110f: return 0x11bf;
01330                         case 0x1110: return 0x11c0;
01331                         case 0x1111: return 0x11c1;
01332                         case 0x1112: return 0x11c2;
01333                         default: return 0;
01334 
01335                 }
01336 
01337         } else { //echar to schar
01338 
01339                 switch (c) {
01340                         case 0x11a8: return 0x1100;
01341                         case 0x11a9: return 0x1101;
01342                         case 0x11ab: return 0x1102;
01343                         case 0x11ae: return 0x1103;
01344                         case 0x11af: return 0x1105;
01345                         case 0x11b7: return 0x1106;
01346                         case 0x11b8: return 0x1107;
01347                         case 0x11ba: return 0x1109;
01348                         case 0x11bb: return 0x110a;
01349                         case 0x11bc: return 0x110b;
01350                         case 0x11bd: return 0x110c;
01351                         case 0x11be: return 0x110e;
01352                         case 0x11bf: return 0x110f;
01353                         case 0x11c0: return 0x1110;
01354                         case 0x11c1: return 0x1111;
01355                         case 0x11c2: return 0x1112;
01356                         default: return 0;
01357 
01358                 }
01359 
01360         }
01361 }
01362 
01363 
01364 // Keys::Keys {{{1
01365 
01366 Keys::Keys() {
01367 
01368     Config *config = new Config ("multikey");
01369     config->setGroup( "keymaps" );
01370     QString map = config->readEntry( "current" );
01371     delete config;
01372 
01373     if (map.isNull() || !(QFile(map).exists())) {
01374 
01375         Config *config = new Config("locale");
01376         config->setGroup( "Language" );
01377         QString l = config->readEntry( "Language" , "en" );
01378         delete config;
01379     
01380         map = QPEApplication::qpeDir() + "share/multikey/" 
01381                 + l + ".keymap";
01382 
01383     } 
01384     if (map.isNull() || !(QFile(map).exists())) {
01385         map = QPEApplication::qpeDir() + "share/multikey/en.keymap";
01386     }
01387     
01388     setKeysFromFile(map);
01389 }
01390 
01391 Keys::Keys(const char * filename) {
01392 
01393     setKeysFromFile(filename);
01394 }
01395 
01396 // Keys::setKeysFromFile {{{2
01397 void Keys::setKeysFromFile(const char * filename) {
01398 
01399     QFile f(filename);
01400 
01401     if (f.open(IO_ReadOnly)) {
01402 
01403         QTextStream t(&f);
01404         int row;
01405         int qcode;
01406         ushort unicode;
01407         int width;
01408         QString buf;
01409         QString comment;
01410         char * xpm[256]; //couldnt be larger than that... could it?
01411         QImage *xpm2pix = 0;
01412 
01413         buf = t.readLine();
01414         while (buf) {
01415 
01416             // get rid of comments
01417             buf.replace(QRegExp("#.*$", FALSE, FALSE), "");
01418 
01419             // key definition
01420             if (buf.contains(QRegExp("^\\d+\\s+[0-1a-fx]+", FALSE, FALSE))) { 
01421             // no $1 type referencing!!! this implementation of regexp sucks
01422 
01423                 // dont know of any sscanf() type funcs in Qt lib
01424                 QTextStream tmp (buf, IO_ReadOnly);
01425                 tmp >> row >> qcode >> unicode >> width >> comment;
01426 
01427                 buf = t.readLine();
01428                 int xpmLineCount = 0;
01429                 xpm2pix = 0;
01430 
01431                 // erase blank space
01432                 while (buf.contains(QRegExp("^\\s*$")) && buf) buf = t.readLine();
01433 
01434                 while (buf.contains(QRegExp("^\\s*\".*\""))) {
01435 
01436                     QString xpmBuf = buf.stripWhiteSpace();
01437 
01438                     xpm[xpmLineCount] = new char [xpmBuf.length()];
01439 
01440                     int j = 0;
01441                     for (ushort i = 0; i < xpmBuf.length(); i++) {
01442                         if (xpmBuf[i].latin1() != '"') {
01443 
01444                             ((char *)xpm[xpmLineCount])[j] = xpmBuf.at(i).latin1();
01445                             j++;
01446                         }
01447 
01448                     }
01449                     // have to close that facker up
01450                     ((char *)xpm[xpmLineCount])[j] = '\0';
01451 
01452                     xpmLineCount++;
01453                     buf = t.readLine();
01454                 }
01455                 if (xpmLineCount) {
01456 
01457                     xpm2pix = new QImage((const char **)xpm);
01458                     for (int i = 0; i < xpmLineCount; i++) 
01459 
01460                         delete [] (xpm[i]);
01461 
01462                 }
01463                 setKey(row, qcode, unicode, width, xpm2pix);
01464             }
01465 
01466             // shift map
01467             else if (buf.contains(QRegExp("^[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01468 
01469                 QTextStream tmp (buf, IO_ReadOnly);
01470                 ushort lower, shift;
01471                 tmp >> lower >> shift;
01472 
01473                 shiftMap.insert(lower, shift);
01474 
01475                 buf = t.readLine();
01476             }
01477 
01478             // meta key map
01479             else if (buf.contains(QRegExp("^\\s*m\\s+[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01480 
01481                 QTextStream tmp (buf, IO_ReadOnly);
01482                 ushort lower, shift;
01483                 QChar m;
01484                 tmp >> m >> lower >> shift;
01485 
01486                 metaMap.insert(lower, shift);
01487 
01488                 buf = t.readLine();
01489             }
01490 
01491             // circumflex
01492             else if (buf.contains(QRegExp("^\\s*c\\s+[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01493 
01494                 QTextStream tmp (buf, IO_ReadOnly);
01495                 ushort lower, shift;
01496                 QChar c;
01497                 tmp >> c >> lower >> shift;
01498 
01499                 circumflexMap.insert(lower, shift);
01500 
01501                 buf = t.readLine();
01502             }
01503             // diaeresis
01504             else if (buf.contains(QRegExp("^\\s*d\\s+[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01505 
01506                 QTextStream tmp (buf, IO_ReadOnly);
01507                 ushort lower, shift;
01508                 QChar d;
01509                 tmp >> d >> lower >> shift;
01510 
01511                 diaeresisMap.insert(lower, shift);
01512 
01513                 buf = t.readLine();
01514             }
01515             // back accent
01516             else if (buf.contains(QRegExp("^\\s*b\\s+[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01517 
01518                 QTextStream tmp (buf, IO_ReadOnly);
01519                 ushort lower, shift;
01520                 QChar d;
01521                 tmp >> d >> lower >> shift;
01522 
01523                 baccentMap.insert(lower, shift);
01524 
01525                 qDebug ("Estoy aadiendo %i con %i", lower, shift);
01526                 buf = t.readLine();
01527             }
01528             // accent
01529             else if (buf.contains(QRegExp("^\\s*a\\s+[0-9a-fx]+\\s+[0-9a-fx]+\\s*$", FALSE, FALSE))) {
01530 
01531                 QTextStream tmp (buf, IO_ReadOnly);
01532                 ushort lower, shift;
01533                 QChar d;
01534                 tmp >> d >> lower >> shift;
01535 
01536                 accentMap.insert(lower, shift);
01537 
01538                 buf = t.readLine();
01539             }
01540 
01541             // other variables like lang & title & sw
01542             else if (buf.contains(QRegExp("^\\s*[a-zA-Z]+\\s*=\\s*[a-zA-Z0-9/]+\\s*$", FALSE, FALSE))) {
01543 
01544                 QTextStream tmp (buf, IO_ReadOnly);
01545                 QString name, equals, value;
01546 
01547                 tmp >> name >> equals >> value;
01548 
01549                 if (name == "lang") {
01550 
01551                     lang = value;
01552 
01553                 } 
01554 
01555                 buf = t.readLine();
01556             }
01557             // comments
01558             else if (buf.contains(QRegExp("^\\s*#"))) {
01559 
01560                 buf = t.readLine();
01561 
01562             } else { // blank line, or garbage
01563 
01564                 buf = t.readLine();
01565 
01566             }
01567 
01568         }
01569         
01570         f.close();
01571     } else {
01572         // We couldnt find the selected keymap, give them a configure button
01573         QImage * btn = new QImage((const char ** )kb_config_xpm);
01574         setKey(1, 0x1030, 0, 2, btn);
01575     }
01576 
01577 }
01578 
01579 
01580 // Keys::setKey {{{2
01581 void Keys::setKey(const int row, const int qcode, const ushort unicode, 
01582                     const int width, QImage *pix) {
01583 
01584     Key * key;
01585     key = new Key; 
01586     key->qcode = qcode;
01587     key->unicode = unicode;
01588     key->width = width;
01589 
01590     // share key->pressed between same keys
01591     bool found = 0;
01592     for (int i = 1; i <= 5; i++) {
01593         for (unsigned int j = 0; j < keys[i].count(); j++)
01594             if (keys[i].at(j)->qcode == qcode && keys[i].at(j)->unicode == unicode) {
01595                
01596                 key->pressed = keys[i].at(j)->pressed;
01597                 found = 1;
01598             }
01599 
01600     }
01601     if (!found) {
01602 
01603         key->pressed = new bool;
01604         *(key->pressed) = 0;
01605     }
01606 
01607     key->pix = pix;
01608 
01609 
01610     keys[row].append(key);
01611 }
01612 
01613 // Keys::~Keys {{{2
01614 Keys::~Keys() {
01615 
01616     for (int i = 1; i <= 5; i++) 
01617         for (unsigned int j = 0; j < keys[i].count(); j++)
01618             delete keys[i].at(j);
01619 
01620 }
01621 
01622 // Keys:: other functions {{{2
01623 int Keys::width(const int row, const int col) {
01624     
01625     return keys[row].at(col)->width;
01626 
01627 }
01628 
01629 int Keys::rows() {
01630 
01631     for (int i = 1; i <= 5; i++) {
01632 
01633         if (keys[i].count() == 0)
01634             return i - 1;
01635 
01636     }
01637     return 5;
01638 }
01639 
01640 ushort Keys::uni(const int row, const int col) {
01641 
01642     return keys[row].at(col)->unicode;
01643 
01644 }
01645 
01646 int Keys::qcode(const int row, const int col) {
01647 
01648     return keys[row].at(col)->qcode;
01649 }
01650 
01651 QImage *Keys::pix(const int row, const int col) {
01652 
01653     return keys[row].at(col)->pix;
01654 
01655 }
01656 bool Keys::pressed(const int row, const int col) {
01657 
01658     return *(keys[row].at(col)->pressed);
01659 }
01660 
01661 int Keys::numKeys(const int row) {
01662 
01663     return keys[row].count();
01664 }
01665 
01666 void Keys::setPressed(const int row, const int col, const bool pressed) {
01667 
01668     *(keys[row].at(col)->pressed) = pressed;
01669 }
01670 
01671 ushort Keys::shift(const ushort uni) {
01672 
01673     if (shiftMap[uni]) return shiftMap[uni]; 
01674     else return 0;
01675 }
01676 
01677 ushort Keys::meta(const ushort uni) {
01678 
01679     if (metaMap[uni]) return metaMap[uni]; 
01680     else return 0;
01681 }
01682 
01683 ushort Keys::circumflex(const ushort uni) {
01684 
01685     if (circumflexMap[uni]) return circumflexMap[uni]; 
01686     else return 0;
01687 }
01688 
01689 ushort Keys::diaeresis(const ushort uni) {
01690 
01691     if(diaeresisMap[uni]) return diaeresisMap[uni];
01692     else return 0;
01693 }
01694 
01695 ushort Keys::baccent(const ushort uni) {
01696 
01697     if(baccentMap[uni]) return baccentMap[uni];
01698     else return 0;
01699 }
01700 
01701 ushort Keys::accent(const ushort uni) {
01702 
01703     if(accentMap[uni]) return accentMap[uni];
01704     else return 0;
01705 }
01706 
01707 bool *Keys::pressedPtr(const int row, const int col) {
01708 
01709     return keys[row].at(col)->pressed;
01710 }

Generated on Sat Nov 5 16:16:03 2005 for OPIE by  doxygen 1.4.2