-rw-r--r-- | inputmethods/handwriting/qimpenchar.cpp | 9 | ||||
-rw-r--r-- | inputmethods/handwriting/qimpeninput.cpp | 24 | ||||
-rw-r--r-- | inputmethods/handwriting/qimpenmatch.cpp | 35 | ||||
-rw-r--r-- | inputmethods/handwriting/qimpenstroke.cpp | 15 | ||||
-rw-r--r-- | inputmethods/handwriting/qimpenwordpick.cpp | 2 |
5 files changed, 45 insertions, 40 deletions
diff --git a/inputmethods/handwriting/qimpenchar.cpp b/inputmethods/handwriting/qimpenchar.cpp index 929f370..db5d135 100644 --- a/inputmethods/handwriting/qimpenchar.cpp +++ b/inputmethods/handwriting/qimpenchar.cpp | |||
@@ -1,76 +1,77 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qtopia Environment. | 4 | ** This file is part of Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | 20 | ||
21 | #include <qfile.h> | 21 | #include <qfile.h> |
22 | #include <qtl.h> | 22 | #include <qtl.h> |
23 | #include <math.h> | 23 | #include <math.h> |
24 | #include <limits.h> | 24 | #include <limits.h> |
25 | #include <errno.h> | 25 | #include <errno.h> |
26 | #include <qdatastream.h> | 26 | #include <qdatastream.h> |
27 | #include "qimpencombining.h" | 27 | #include "qimpencombining.h" |
28 | #include "qimpenchar.h" | 28 | #include "qimpenchar.h" |
29 | #include "opie2/odebug.h" | ||
29 | 30 | ||
30 | #define QIMPEN_MATCH_THRESHOLD 200000 | 31 | #define QIMPEN_MATCH_THRESHOLD 200000 |
31 | 32 | ||
32 | const QIMPenSpecialKeys qimpen_specialKeys[] = { | 33 | const QIMPenSpecialKeys qimpen_specialKeys[] = { |
33 | { Qt::Key_Escape, "[Esc]" }, | 34 | { Qt::Key_Escape, "[Esc]" }, |
34 | { Qt::Key_Tab, "[Tab]" }, | 35 | { Qt::Key_Tab, "[Tab]" }, |
35 | { Qt::Key_Backspace,"[BackSpace]" }, | 36 | { Qt::Key_Backspace,"[BackSpace]" }, |
36 | { Qt::Key_Return, "[Return]" }, | 37 | { Qt::Key_Return, "[Return]" }, |
37 | { QIMPenChar::Caps, "[Uppercase]" }, | 38 | { QIMPenChar::Caps, "[Uppercase]" }, |
38 | { QIMPenChar::CapsLock,"[Caps Lock]" }, | 39 | { QIMPenChar::CapsLock,"[Caps Lock]" }, |
39 | { QIMPenChar::Shortcut,"[Shortcut]" }, | 40 | { QIMPenChar::Shortcut,"[Shortcut]" }, |
40 | { QIMPenChar::Punctuation, "[Punctuation]" }, | 41 | { QIMPenChar::Punctuation, "[Punctuation]" }, |
41 | { QIMPenChar::Symbol,"[Symbol]" }, | 42 | { QIMPenChar::Symbol,"[Symbol]" }, |
42 | { QIMPenChar::Extended,"[Extended]" }, | 43 | { QIMPenChar::Extended,"[Extended]" }, |
43 | { Qt::Key_unknown, 0 } }; | 44 | { Qt::Key_unknown, 0 } }; |
44 | 45 | ||
45 | 46 | ||
46 | /*! | 47 | /*! |
47 | \class QIMPenChar qimpenchar.h | 48 | \class QIMPenChar qimpenchar.h |
48 | 49 | ||
49 | Handles a single character. Can calculate closeness of match to | 50 | Handles a single character. Can calculate closeness of match to |
50 | another character. | 51 | another character. |
51 | */ | 52 | */ |
52 | 53 | ||
53 | QIMPenChar::QIMPenChar() | 54 | QIMPenChar::QIMPenChar() |
54 | { | 55 | { |
55 | flags = 0; | 56 | flags = 0; |
56 | strokes.setAutoDelete( TRUE ); | 57 | strokes.setAutoDelete( TRUE ); |
57 | } | 58 | } |
58 | 59 | ||
59 | QIMPenChar::QIMPenChar( const QIMPenChar &chr ) | 60 | QIMPenChar::QIMPenChar( const QIMPenChar &chr ) |
60 | { | 61 | { |
61 | strokes.setAutoDelete( TRUE ); | 62 | strokes.setAutoDelete( TRUE ); |
62 | ch = chr.ch; | 63 | ch = chr.ch; |
63 | flags = chr.flags; | 64 | flags = chr.flags; |
64 | d = chr.d; | 65 | d = chr.d; |
65 | QIMPenStrokeIterator it( chr.strokes ); | 66 | QIMPenStrokeIterator it( chr.strokes ); |
66 | while ( it.current() ) { | 67 | while ( it.current() ) { |
67 | strokes.append( new QIMPenStroke( *it.current() ) ); | 68 | strokes.append( new QIMPenStroke( *it.current() ) ); |
68 | ++it; | 69 | ++it; |
69 | } | 70 | } |
70 | } | 71 | } |
71 | 72 | ||
72 | QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr ) | 73 | QIMPenChar &QIMPenChar::operator=( const QIMPenChar &chr ) |
73 | { | 74 | { |
74 | strokes.clear(); | 75 | strokes.clear(); |
75 | ch = chr.ch; | 76 | ch = chr.ch; |
76 | flags = chr.flags; | 77 | flags = chr.flags; |
@@ -122,112 +123,112 @@ unsigned int QIMPenChar::strokeLength( int s ) const | |||
122 | if ( it.current() ) | 123 | if ( it.current() ) |
123 | return it.current()->length(); | 124 | return it.current()->length(); |
124 | 125 | ||
125 | return 0; | 126 | return 0; |
126 | } | 127 | } |
127 | 128 | ||
128 | /*! | 129 | /*! |
129 | Add a stroke to the character | 130 | Add a stroke to the character |
130 | */ | 131 | */ |
131 | void QIMPenChar::addStroke( QIMPenStroke *st ) | 132 | void QIMPenChar::addStroke( QIMPenStroke *st ) |
132 | { | 133 | { |
133 | QIMPenStroke *stroke = new QIMPenStroke( *st ); | 134 | QIMPenStroke *stroke = new QIMPenStroke( *st ); |
134 | strokes.append( stroke ); | 135 | strokes.append( stroke ); |
135 | } | 136 | } |
136 | 137 | ||
137 | /*! | 138 | /*! |
138 | Return an indicator of the closeness of this character to \a pen. | 139 | Return an indicator of the closeness of this character to \a pen. |
139 | Lower value is better. | 140 | Lower value is better. |
140 | */ | 141 | */ |
141 | int QIMPenChar::match( QIMPenChar *pen ) | 142 | int QIMPenChar::match( QIMPenChar *pen ) |
142 | { | 143 | { |
143 | /* | 144 | /* |
144 | if ( strokes.count() > pen->strokes.count() ) | 145 | if ( strokes.count() > pen->strokes.count() ) |
145 | return INT_MAX; | 146 | return INT_MAX; |
146 | */ | 147 | */ |
147 | int err = 0; | 148 | int err = 0; |
148 | int maxErr = 0; | 149 | int maxErr = 0; |
149 | int diff = 0; | 150 | int diff = 0; |
150 | QIMPenStrokeIterator it1( strokes ); | 151 | QIMPenStrokeIterator it1( strokes ); |
151 | QIMPenStrokeIterator it2( pen->strokes ); | 152 | QIMPenStrokeIterator it2( pen->strokes ); |
152 | err = it1.current()->match( it2.current() ); | 153 | err = it1.current()->match( it2.current() ); |
153 | if ( err > maxErr ) | 154 | if ( err > maxErr ) |
154 | maxErr = err; | 155 | maxErr = err; |
155 | ++it1; | 156 | ++it1; |
156 | ++it2; | 157 | ++it2; |
157 | while ( err < 400000 && it1.current() && it2.current() ) { | 158 | while ( err < 400000 && it1.current() && it2.current() ) { |
158 | QPoint p1 = it1.current()->boundingRect().center() - | 159 | QPoint p1 = it1.current()->boundingRect().center() - |
159 | strokes.getFirst()->boundingRect().center(); | 160 | strokes.getFirst()->boundingRect().center(); |
160 | QPoint p2 = it2.current()->boundingRect().center() - | 161 | QPoint p2 = it2.current()->boundingRect().center() - |
161 | pen->strokes.getFirst()->boundingRect().center(); | 162 | pen->strokes.getFirst()->boundingRect().center(); |
162 | int xdiff = QABS( p1.x() - p2.x() ) - 6; | 163 | int xdiff = QABS( p1.x() - p2.x() ) - 6; |
163 | int ydiff = QABS( p1.y() - p2.y() ) - 5; | 164 | int ydiff = QABS( p1.y() - p2.y() ) - 5; |
164 | if ( xdiff < 0 ) | 165 | if ( xdiff < 0 ) |
165 | xdiff = 0; | 166 | xdiff = 0; |
166 | if ( ydiff < 0 ) | 167 | if ( ydiff < 0 ) |
167 | ydiff = 0; | 168 | ydiff = 0; |
168 | if ( xdiff > 10 || ydiff > 10 ) { // not a chance | 169 | if ( xdiff > 10 || ydiff > 10 ) { // not a chance |
169 | #ifdef DEBUG_QIMPEN | 170 | #ifdef DEBUG_QIMPEN |
170 | qDebug( "char %c, stroke starting pt diff excessive", pen->ch ); | 171 | odebug << "char " << pen->ch <<", stroke starting pt diff excessive" << oendl; |
171 | #endif | 172 | #endif |
172 | return INT_MAX; | 173 | return INT_MAX; |
173 | } | 174 | } |
174 | diff += xdiff*xdiff + ydiff*ydiff; | 175 | diff += xdiff*xdiff + ydiff*ydiff; |
175 | err = it1.current()->match( it2.current() ); | 176 | err = it1.current()->match( it2.current() ); |
176 | if ( err > maxErr ) | 177 | if ( err > maxErr ) |
177 | maxErr = err; | 178 | maxErr = err; |
178 | ++it1; | 179 | ++it1; |
179 | ++it2; | 180 | ++it2; |
180 | } | 181 | } |
181 | 182 | ||
182 | maxErr += diff * diff * 6; // magic weighting :) | 183 | maxErr += diff * diff * 6; // magic weighting :) |
183 | 184 | ||
184 | #ifdef DEBUG_QIMPEN | 185 | #ifdef DEBUG_QIMPEN |
185 | qDebug( "char: %c, maxErr %d, diff %d, (%d)", pen->ch, maxErr, diff, strokes.count() ); | 186 | odebug << "char: " << pen->ch << ", maxErr " << maxErr << ", diff " << diff << ", " << strokes.count() << oendl; |
186 | #endif | 187 | #endif |
187 | return maxErr; | 188 | return maxErr; |
188 | } | 189 | } |
189 | 190 | ||
190 | /*! | 191 | /*! |
191 | Return the bounding rect of this character. It may have sides with | 192 | Return the bounding rect of this character. It may have sides with |
192 | negative coords since its origin is where the user started drawing | 193 | negative coords since its origin is where the user started drawing |
193 | the character. | 194 | the character. |
194 | */ | 195 | */ |
195 | QRect QIMPenChar::boundingRect() | 196 | QRect QIMPenChar::boundingRect() |
196 | { | 197 | { |
197 | QRect br; | 198 | QRect br; |
198 | QIMPenStroke *st = strokes.first(); | 199 | QIMPenStroke *st = strokes.first(); |
199 | while ( st ) { | 200 | while ( st ) { |
200 | br |= st->boundingRect(); | 201 | br |= st->boundingRect(); |
201 | st = strokes.next(); | 202 | st = strokes.next(); |
202 | } | 203 | } |
203 | 204 | ||
204 | return br; | 205 | return br; |
205 | } | 206 | } |
206 | 207 | ||
207 | 208 | ||
208 | /*! | 209 | /*! |
209 | Write the character's data to the stream. | 210 | Write the character's data to the stream. |
210 | */ | 211 | */ |
211 | QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws) | 212 | QDataStream &operator<< (QDataStream &s, const QIMPenChar &ws) |
212 | { | 213 | { |
213 | s << ws.ch; | 214 | s << ws.ch; |
214 | s << ws.flags; | 215 | s << ws.flags; |
215 | if ( ws.flags & QIMPenChar::Data ) | 216 | if ( ws.flags & QIMPenChar::Data ) |
216 | s << ws.d; | 217 | s << ws.d; |
217 | s << ws.strokes.count(); | 218 | s << ws.strokes.count(); |
218 | QIMPenStrokeIterator it( ws.strokes ); | 219 | QIMPenStrokeIterator it( ws.strokes ); |
219 | while ( it.current() ) { | 220 | while ( it.current() ) { |
220 | s << *it.current(); | 221 | s << *it.current(); |
221 | ++it; | 222 | ++it; |
222 | } | 223 | } |
223 | 224 | ||
224 | return s; | 225 | return s; |
225 | } | 226 | } |
226 | 227 | ||
227 | /*! | 228 | /*! |
228 | Read the character's data from the stream. | 229 | Read the character's data from the stream. |
229 | */ | 230 | */ |
230 | QDataStream &operator>> (QDataStream &s, QIMPenChar &ws) | 231 | QDataStream &operator>> (QDataStream &s, QIMPenChar &ws) |
231 | { | 232 | { |
232 | s >> ws.ch; | 233 | s >> ws.ch; |
233 | s >> ws.flags; | 234 | s >> ws.flags; |
@@ -413,98 +414,98 @@ void QIMPenCharSet::markDeleted( uint ch ) | |||
413 | for ( ; ci.current(); ++ci ) { | 414 | for ( ; ci.current(); ++ci ) { |
414 | QIMPenChar *pc = ci.current(); | 415 | QIMPenChar *pc = ci.current(); |
415 | if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) ) | 416 | if ( pc->character() == ch && pc->testFlag( QIMPenChar::System ) ) |
416 | pc->setFlag( QIMPenChar::Deleted ); | 417 | pc->setFlag( QIMPenChar::Deleted ); |
417 | } | 418 | } |
418 | } | 419 | } |
419 | 420 | ||
420 | /*! | 421 | /*! |
421 | Find the best matches for \a ch in this character set. | 422 | Find the best matches for \a ch in this character set. |
422 | */ | 423 | */ |
423 | QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch ) | 424 | QIMPenCharMatchList QIMPenCharSet::match( QIMPenChar *ch ) |
424 | { | 425 | { |
425 | QIMPenCharMatchList matches; | 426 | QIMPenCharMatchList matches; |
426 | 427 | ||
427 | QIMPenCharIterator ci( chars ); | 428 | QIMPenCharIterator ci( chars ); |
428 | for ( ; ci.current(); ++ci ) { | 429 | for ( ; ci.current(); ++ci ) { |
429 | QIMPenChar *tmplChar = ci.current(); | 430 | QIMPenChar *tmplChar = ci.current(); |
430 | if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) { | 431 | if ( tmplChar->testFlag( QIMPenChar::Deleted ) ) { |
431 | continue; | 432 | continue; |
432 | } | 433 | } |
433 | int err; | 434 | int err; |
434 | if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) { | 435 | if ( ch->penStrokes().count() <= tmplChar->penStrokes().count() ) { |
435 | err = ch->match( tmplChar ); | 436 | err = ch->match( tmplChar ); |
436 | if ( err <= QIMPEN_MATCH_THRESHOLD ) { | 437 | if ( err <= QIMPEN_MATCH_THRESHOLD ) { |
437 | if (tmplChar->penStrokes().count() != ch->penStrokes().count()) | 438 | if (tmplChar->penStrokes().count() != ch->penStrokes().count()) |
438 | err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD); | 439 | err = QMIN(err*3, QIMPEN_MATCH_THRESHOLD); |
439 | QIMPenCharMatchList::Iterator it; | 440 | QIMPenCharMatchList::Iterator it; |
440 | for ( it = matches.begin(); it != matches.end(); ++it ) { | 441 | for ( it = matches.begin(); it != matches.end(); ++it ) { |
441 | if ( (*it).penChar->character() == tmplChar->character() && | 442 | if ( (*it).penChar->character() == tmplChar->character() && |
442 | (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) { | 443 | (*it).penChar->penStrokes().count() == tmplChar->penStrokes().count() ) { |
443 | if ( (*it).error > err ) | 444 | if ( (*it).error > err ) |
444 | (*it).error = err; | 445 | (*it).error = err; |
445 | break; | 446 | break; |
446 | } | 447 | } |
447 | } | 448 | } |
448 | if ( it == matches.end() ) { | 449 | if ( it == matches.end() ) { |
449 | QIMPenCharMatch m; | 450 | QIMPenCharMatch m; |
450 | m.error = err; | 451 | m.error = err; |
451 | m.penChar = tmplChar; | 452 | m.penChar = tmplChar; |
452 | matches.append( m ); | 453 | matches.append( m ); |
453 | } | 454 | } |
454 | } | 455 | } |
455 | } | 456 | } |
456 | } | 457 | } |
457 | qHeapSort( matches ); | 458 | qHeapSort( matches ); |
458 | /* | 459 | /* |
459 | QIMPenCharMatchList::Iterator it; | 460 | QIMPenCharMatchList::Iterator it; |
460 | for ( it = matches.begin(); it != matches.end(); ++it ) { | 461 | for ( it = matches.begin(); it != matches.end(); ++it ) { |
461 | qDebug( "Match: \'%c\', error %d, strokes %d", (*it).penChar->character(), | 462 | |
462 | (*it).error, (*it).penChar->penStrokes().count() ); | 463 | odebug << "Match: \'" << (*it).penChar->character() "\', error " << (*it).error ", strokes " <<(*it).penChar->penStrokes().count() << oendl; |
463 | } | 464 | } |
464 | */ | 465 | */ |
465 | return matches; | 466 | return matches; |
466 | } | 467 | } |
467 | 468 | ||
468 | /*! | 469 | /*! |
469 | Add a character \a ch to this set. | 470 | Add a character \a ch to this set. |
470 | QIMPenCharSet will delete this character when it is no longer needed. | 471 | QIMPenCharSet will delete this character when it is no longer needed. |
471 | */ | 472 | */ |
472 | void QIMPenCharSet::addChar( QIMPenChar *ch ) | 473 | void QIMPenCharSet::addChar( QIMPenChar *ch ) |
473 | { | 474 | { |
474 | if ( ch->penStrokes().count() > maxStrokes ) | 475 | if ( ch->penStrokes().count() > maxStrokes ) |
475 | maxStrokes = ch->penStrokes().count(); | 476 | maxStrokes = ch->penStrokes().count(); |
476 | chars.append( ch ); | 477 | chars.append( ch ); |
477 | } | 478 | } |
478 | 479 | ||
479 | /*! | 480 | /*! |
480 | Remove a character by reference \a ch from this set. | 481 | Remove a character by reference \a ch from this set. |
481 | QIMPenCharSet will delete this character. | 482 | QIMPenCharSet will delete this character. |
482 | */ | 483 | */ |
483 | void QIMPenCharSet::removeChar( QIMPenChar *ch ) | 484 | void QIMPenCharSet::removeChar( QIMPenChar *ch ) |
484 | { | 485 | { |
485 | chars.remove( ch ); | 486 | chars.remove( ch ); |
486 | } | 487 | } |
487 | 488 | ||
488 | /*! | 489 | /*! |
489 | Move the character up the list of characters. | 490 | Move the character up the list of characters. |
490 | */ | 491 | */ |
491 | void QIMPenCharSet::up( QIMPenChar *ch ) | 492 | void QIMPenCharSet::up( QIMPenChar *ch ) |
492 | { | 493 | { |
493 | int idx = chars.findRef( ch ); | 494 | int idx = chars.findRef( ch ); |
494 | if ( idx > 0 ) { | 495 | if ( idx > 0 ) { |
495 | chars.take(); | 496 | chars.take(); |
496 | chars.insert( idx - 1, ch ); | 497 | chars.insert( idx - 1, ch ); |
497 | } | 498 | } |
498 | } | 499 | } |
499 | 500 | ||
500 | /*! | 501 | /*! |
501 | Move the character down the list of characters. | 502 | Move the character down the list of characters. |
502 | */ | 503 | */ |
503 | void QIMPenCharSet::down( QIMPenChar *ch ) | 504 | void QIMPenCharSet::down( QIMPenChar *ch ) |
504 | { | 505 | { |
505 | int idx = chars.findRef( ch ); | 506 | int idx = chars.findRef( ch ); |
506 | if ( idx >= 0 && idx < (int)chars.count() - 1 ) { | 507 | if ( idx >= 0 && idx < (int)chars.count() - 1 ) { |
507 | chars.take(); | 508 | chars.take(); |
508 | chars.insert( idx + 1, ch ); | 509 | chars.insert( idx + 1, ch ); |
509 | } | 510 | } |
510 | } | 511 | } |
diff --git a/inputmethods/handwriting/qimpeninput.cpp b/inputmethods/handwriting/qimpeninput.cpp index d073cdf..6ea1bb4 100644 --- a/inputmethods/handwriting/qimpeninput.cpp +++ b/inputmethods/handwriting/qimpeninput.cpp | |||
@@ -1,86 +1,87 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of the Qtopia Environment. | 4 | ** This file is part of the Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | 20 | ||
21 | #include "qimpenwidget.h" | 21 | #include "qimpenwidget.h" |
22 | #include "qimpensetup.h" | 22 | #include "qimpensetup.h" |
23 | #include "qimpeninput.h" | 23 | #include "qimpeninput.h" |
24 | #include "qimpencombining.h" | 24 | #include "qimpencombining.h" |
25 | #include "qimpenwordpick.h" | 25 | #include "qimpenwordpick.h" |
26 | #include "qimpenmatch.h" | 26 | #include "qimpenmatch.h" |
27 | #include "qimpenhelp.h" | 27 | #include "qimpenhelp.h" |
28 | 28 | ||
29 | #include <qpe/qpeapplication.h> | 29 | #include <qpe/qpeapplication.h> |
30 | #include <qpe/qdawg.h> | 30 | #include <qpe/qdawg.h> |
31 | #include <qpe/config.h> | 31 | #include <qpe/config.h> |
32 | #include <qpe/global.h> | 32 | #include <qpe/global.h> |
33 | 33 | ||
34 | #include <qlayout.h> | 34 | #include <qlayout.h> |
35 | #include <qpushbutton.h> | 35 | #include <qpushbutton.h> |
36 | #include <qlabel.h> | 36 | #include <qlabel.h> |
37 | #include <qtimer.h> | 37 | #include <qtimer.h> |
38 | #include <qdir.h> | 38 | #include <qdir.h> |
39 | #include <opie2/odebug.h> | ||
39 | 40 | ||
40 | #include <limits.h> | 41 | #include <limits.h> |
41 | 42 | ||
42 | // We'll use little pixmaps for the buttons to save screen space. | 43 | // We'll use little pixmaps for the buttons to save screen space. |
43 | 44 | ||
44 | /* XPM */ | 45 | /* XPM */ |
45 | static const char * const pen_xpm[] = { | 46 | static const char * const pen_xpm[] = { |
46 | "12 12 4 1", | 47 | "12 12 4 1", |
47 | " c None", | 48 | " c None", |
48 | ".c #000000", | 49 | ".c #000000", |
49 | "+c #FFFFFF", | 50 | "+c #FFFFFF", |
50 | "@c #808080", | 51 | "@c #808080", |
51 | " . ", | 52 | " . ", |
52 | " .+. ", | 53 | " .+. ", |
53 | " ..@@.", | 54 | " ..@@.", |
54 | " .+@.. ", | 55 | " .+@.. ", |
55 | " .+@@. ", | 56 | " .+@@. ", |
56 | " .+@@. ", | 57 | " .+@@. ", |
57 | " .+@@. ", | 58 | " .+@@. ", |
58 | " .@.@. ", | 59 | " .@.@. ", |
59 | " .@@. ", | 60 | " .@@. ", |
60 | " .... ", | 61 | " .... ", |
61 | " .. ", | 62 | " .. ", |
62 | " "}; | 63 | " "}; |
63 | 64 | ||
64 | 65 | ||
65 | /* XPM */ | 66 | /* XPM */ |
66 | static char * bs_xpm[] = { | 67 | static char * bs_xpm[] = { |
67 | "12 12 5 1", | 68 | "12 12 5 1", |
68 | " c None", | 69 | " c None", |
69 | ".c #333333", | 70 | ".c #333333", |
70 | "+c #000000", | 71 | "+c #000000", |
71 | "@c #FFFFFF", | 72 | "@c #FFFFFF", |
72 | "#c #666666", | 73 | "#c #666666", |
73 | " ", | 74 | " ", |
74 | " ", | 75 | " ", |
75 | " ", | 76 | " ", |
76 | " . ", | 77 | " . ", |
77 | " ++ ", | 78 | " ++ ", |
78 | " +@#+++++. ", | 79 | " +@#+++++. ", |
79 | " +@@@@@@@@+ ", | 80 | " +@@@@@@@@+ ", |
80 | " +@#+++++. ", | 81 | " +@#+++++. ", |
81 | " ++ ", | 82 | " ++ ", |
82 | " . ", | 83 | " . ", |
83 | " ", | 84 | " ", |
84 | " "}; | 85 | " "}; |
85 | 86 | ||
86 | 87 | ||
@@ -274,237 +275,238 @@ void QIMPenInput::selectProfile( const QString &name ) | |||
274 | return; | 275 | return; |
275 | 276 | ||
276 | pw->clearCharSets(); | 277 | pw->clearCharSets(); |
277 | baseSets.clear(); | 278 | baseSets.clear(); |
278 | 279 | ||
279 | matcher->setMultiStrokeTimeout( profile->multiStrokeTimeout() ); | 280 | matcher->setMultiStrokeTimeout( profile->multiStrokeTimeout() ); |
280 | matcher->setWordMatchingEnabled( profile->matchWords() ); | 281 | matcher->setWordMatchingEnabled( profile->matchWords() ); |
281 | 282 | ||
282 | if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() ) | 283 | if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() ) |
283 | wordPicker->hide(); | 284 | wordPicker->hide(); |
284 | else | 285 | else |
285 | wordPicker->show(); | 286 | wordPicker->show(); |
286 | 287 | ||
287 | if ( profile->uppercase() && profile->style() == QIMPenProfile::BothCases ) { | 288 | if ( profile->uppercase() && profile->style() == QIMPenProfile::BothCases ) { |
288 | baseSets.append( profile->uppercase() ); | 289 | baseSets.append( profile->uppercase() ); |
289 | pw->insertCharSet( profile->uppercase() ); | 290 | pw->insertCharSet( profile->uppercase() ); |
290 | } | 291 | } |
291 | 292 | ||
292 | if ( profile->lowercase() ) { | 293 | if ( profile->lowercase() ) { |
293 | baseSets.append( profile->lowercase() ); | 294 | baseSets.append( profile->lowercase() ); |
294 | pw->insertCharSet( profile->lowercase(), profile->style() == QIMPenProfile::BothCases ? 1 : 2 ); | 295 | pw->insertCharSet( profile->lowercase(), profile->style() == QIMPenProfile::BothCases ? 1 : 2 ); |
295 | } | 296 | } |
296 | 297 | ||
297 | if ( profile->numeric() ) { | 298 | if ( profile->numeric() ) { |
298 | baseSets.append( profile->numeric() ); | 299 | baseSets.append( profile->numeric() ); |
299 | pw->insertCharSet( profile->numeric() ); | 300 | pw->insertCharSet( profile->numeric() ); |
300 | } | 301 | } |
301 | 302 | ||
302 | if ( helpDlg ) | 303 | if ( helpDlg ) |
303 | delete (HandwritingHelp*) helpDlg; | 304 | delete (HandwritingHelp*) helpDlg; |
304 | } | 305 | } |
305 | 306 | ||
306 | void QIMPenInput::wordPicked( const QString &w ) | 307 | void QIMPenInput::wordPicked( const QString &w ) |
307 | { | 308 | { |
308 | int bs = matcher->word().length(); | 309 | int bs = matcher->word().length(); |
309 | for ( int i = 0; i < bs; i++ ) | 310 | for ( int i = 0; i < bs; i++ ) |
310 | keypress( Qt::Key_Backspace << 16 ); | 311 | keypress( Qt::Key_Backspace << 16 ); |
311 | 312 | ||
312 | for ( unsigned int i = 0; i < w.length(); i++ ) | 313 | for ( unsigned int i = 0; i < w.length(); i++ ) |
313 | keypress( w[i].unicode() ); | 314 | keypress( w[i].unicode() ); |
314 | 315 | ||
315 | matcher->resetState(); | 316 | matcher->resetState(); |
316 | wordPicker->clear(); | 317 | wordPicker->clear(); |
317 | } | 318 | } |
318 | 319 | ||
319 | void QIMPenInput::selectCharSet( int idx ) | 320 | void QIMPenInput::selectCharSet( int idx ) |
320 | { | 321 | { |
321 | if ( mode == Switch ) { | 322 | if ( mode == Switch ) { |
322 | //qDebug( "Switch back to normal" ); | 323 | //odebug << "Switch back to normal" << oendl; |
323 | pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); | 324 | pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); |
324 | mode = Normal; | 325 | mode = Normal; |
325 | } | 326 | } |
326 | currCharSet = idx; | 327 | currCharSet = idx; |
327 | } | 328 | } |
328 | 329 | ||
329 | void QIMPenInput::beginStroke() | 330 | void QIMPenInput::beginStroke() |
330 | { | 331 | { |
331 | } | 332 | } |
332 | 333 | ||
333 | void QIMPenInput::strokeEntered( QIMPenStroke * ) | 334 | void QIMPenInput::strokeEntered( QIMPenStroke * ) |
334 | { | 335 | { |
335 | pw->greyStroke(); | 336 | pw->greyStroke(); |
336 | } | 337 | } |
337 | 338 | ||
338 | void QIMPenInput::erase() | 339 | void QIMPenInput::erase() |
339 | { | 340 | { |
340 | keypress( Qt::Key_Backspace << 16 ); | 341 | keypress( Qt::Key_Backspace << 16 ); |
341 | } | 342 | } |
342 | 343 | ||
343 | void QIMPenInput::matchedCharacters( const QIMPenCharMatchList &cl ) | 344 | void QIMPenInput::matchedCharacters( const QIMPenCharMatchList &cl ) |
344 | { | 345 | { |
345 | const QIMPenChar *ch = cl.first().penChar; | 346 | const QIMPenChar *ch = cl.first().penChar; |
346 | int scan = ch->character() >> 16; | 347 | int scan = ch->character() >> 16; |
347 | 348 | ||
348 | if ( scan < QIMPenChar::ModeBase ) | 349 | if ( scan < QIMPenChar::ModeBase ) |
349 | return; | 350 | return; |
350 | 351 | ||
351 | // We matched a special character... | 352 | // We matched a special character... |
352 | 353 | ||
353 | switch ( scan ) { | 354 | switch ( scan ) { |
354 | case QIMPenChar::Caps: | 355 | case QIMPenChar::Caps: |
355 | if ( profile->style() == QIMPenProfile::ToggleCases ) { | 356 | if ( profile->style() == QIMPenProfile::ToggleCases ) { |
356 | // qDebug( "Caps" ); | 357 | // odebug << "Caps" << oendl; |
358 | // | ||
357 | if ( mode == SwitchLock ) { | 359 | if ( mode == SwitchLock ) { |
358 | // qDebug( "Switch to normal" ); | 360 | // odebug << "Switch to normal" << oendl; |
359 | pw->changeCharSet( profile->lowercase(), currCharSet ); | 361 | pw->changeCharSet( profile->lowercase(), currCharSet ); |
360 | mode = Switch; | 362 | mode = Switch; |
361 | } else { | 363 | } else { |
362 | // qDebug( "Switch to upper" ); | 364 | // odebug << "Switch to upper" << oendl; |
363 | pw->changeCharSet( profile->uppercase(), currCharSet ); | 365 | pw->changeCharSet( profile->uppercase(), currCharSet ); |
364 | mode = Switch; | 366 | mode = Switch; |
365 | } | 367 | } |
366 | } | 368 | } |
367 | break; | 369 | break; |
368 | case QIMPenChar::CapsLock: | 370 | case QIMPenChar::CapsLock: |
369 | if ( profile->style() == QIMPenProfile::ToggleCases ) { | 371 | if ( profile->style() == QIMPenProfile::ToggleCases ) { |
370 | // qDebug( "CapsLock" ); | 372 | // odebug << "CapsLock" << oendl; |
371 | if ( mode == Switch && | 373 | if ( mode == Switch && |
372 | baseSets.at(currCharSet) == profile->uppercase() ) { | 374 | baseSets.at(currCharSet) == profile->uppercase() ) { |
373 | // qDebug( "Switch to normal" ); | 375 | // odebug << "Switch to normal" << oendl; |
374 | pw->changeCharSet( profile->lowercase(), currCharSet ); | 376 | pw->changeCharSet( profile->lowercase(), currCharSet ); |
375 | // change our base set back to lower. | 377 | // change our base set back to lower. |
376 | baseSets.remove( currCharSet ); | 378 | baseSets.remove( currCharSet ); |
377 | baseSets.insert( currCharSet, profile->lowercase() ); | 379 | baseSets.insert( currCharSet, profile->lowercase() ); |
378 | mode = Normal; | 380 | mode = Normal; |
379 | } else { | 381 | } else { |
380 | // qDebug( "Switch to caps lock" ); | 382 | // odebug << "Switch to caps lock" << oendl; |
381 | pw->changeCharSet( profile->uppercase(), currCharSet ); | 383 | pw->changeCharSet( profile->uppercase(), currCharSet ); |
382 | // change our base set to upper. | 384 | // change our base set to upper. |
383 | baseSets.remove( currCharSet ); | 385 | baseSets.remove( currCharSet ); |
384 | baseSets.insert( currCharSet, profile->uppercase() ); | 386 | baseSets.insert( currCharSet, profile->uppercase() ); |
385 | mode = SwitchLock; | 387 | mode = SwitchLock; |
386 | } | 388 | } |
387 | } | 389 | } |
388 | break; | 390 | break; |
389 | case QIMPenChar::Punctuation: | 391 | case QIMPenChar::Punctuation: |
390 | if ( profile->punctuation() ) { | 392 | if ( profile->punctuation() ) { |
391 | //qDebug( "Switch to punctuation" ); | 393 | //odebug << "Switch to punctuation" << oendl; |
392 | pw->changeCharSet( profile->punctuation(), currCharSet ); | 394 | pw->changeCharSet( profile->punctuation(), currCharSet ); |
393 | mode = Switch; | 395 | mode = Switch; |
394 | } | 396 | } |
395 | break; | 397 | break; |
396 | case QIMPenChar::Symbol: | 398 | case QIMPenChar::Symbol: |
397 | if ( profile->symbol() ) { | 399 | if ( profile->symbol() ) { |
398 | //qDebug( "Switch to symbol" ); | 400 | //odebug << "Switch to symbol" << oendl ; |
399 | pw->changeCharSet( profile->symbol(), currCharSet ); | 401 | pw->changeCharSet( profile->symbol(), currCharSet ); |
400 | mode = Switch; | 402 | mode = Switch; |
401 | } | 403 | } |
402 | break; | 404 | break; |
403 | case QIMPenChar::Shortcut: | 405 | case QIMPenChar::Shortcut: |
404 | if ( shortcutCharSet ) { | 406 | if ( shortcutCharSet ) { |
405 | pw->changeCharSet( shortcutCharSet, currCharSet ); | 407 | pw->changeCharSet( shortcutCharSet, currCharSet ); |
406 | mode = Switch; | 408 | mode = Switch; |
407 | } | 409 | } |
408 | break; | 410 | break; |
409 | case QIMPenChar::Extended: | 411 | case QIMPenChar::Extended: |
410 | handleExtended( ch->data() ); | 412 | handleExtended( ch->data() ); |
411 | break; | 413 | break; |
412 | } | 414 | } |
413 | } | 415 | } |
414 | 416 | ||
415 | void QIMPenInput::keypress( uint scan_uni ) | 417 | void QIMPenInput::keypress( uint scan_uni ) |
416 | { | 418 | { |
417 | int scan = scan_uni >> 16; | 419 | int scan = scan_uni >> 16; |
418 | if ( !scan ) { | 420 | if ( !scan ) { |
419 | if ( scan_uni >= 'a' && scan_uni <= 'z' ) { | 421 | if ( scan_uni >= 'a' && scan_uni <= 'z' ) { |
420 | scan = Qt::Key_A + scan_uni - 'a'; | 422 | scan = Qt::Key_A + scan_uni - 'a'; |
421 | } else if ( scan_uni >= 'A' && scan_uni <= 'Z' ) { | 423 | } else if ( scan_uni >= 'A' && scan_uni <= 'Z' ) { |
422 | scan = Qt::Key_A + scan_uni - 'A'; | 424 | scan = Qt::Key_A + scan_uni - 'A'; |
423 | } else if ( scan_uni == ' ' ) { | 425 | } else if ( scan_uni == ' ' ) { |
424 | scan = Qt::Key_Space; | 426 | scan = Qt::Key_Space; |
425 | } | 427 | } |
426 | } | 428 | } |
427 | 429 | ||
428 | switch ( scan ) { | 430 | switch ( scan ) { |
429 | case Key_Tab: | 431 | case Key_Tab: |
430 | scan_uni = 9; | 432 | scan_uni = 9; |
431 | break; | 433 | break; |
432 | case Key_Return: | 434 | case Key_Return: |
433 | scan_uni = 13; | 435 | scan_uni = 13; |
434 | break; | 436 | break; |
435 | case Key_Backspace: | 437 | case Key_Backspace: |
436 | scan_uni = 8; | 438 | scan_uni = 8; |
437 | break; | 439 | break; |
438 | case Key_Escape: | 440 | case Key_Escape: |
439 | scan_uni = 27; | 441 | scan_uni = 27; |
440 | break; | 442 | break; |
441 | default: | 443 | default: |
442 | break; | 444 | break; |
443 | } | 445 | } |
444 | 446 | ||
445 | if ( mode == Switch ) { | 447 | if ( mode == Switch ) { |
446 | //qDebug( "Switch back to normal" ); | 448 | //odebug << "Switch back to normal" << oendl ; |
447 | pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); | 449 | pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); |
448 | if ( baseSets.at(currCharSet) == profile->uppercase() ) | 450 | if ( baseSets.at(currCharSet) == profile->uppercase() ) |
449 | mode = SwitchLock; | 451 | mode = SwitchLock; |
450 | else | 452 | else |
451 | mode = Normal; | 453 | mode = Normal; |
452 | } | 454 | } |
453 | 455 | ||
454 | emit key( scan_uni&0xffff, scan, 0, true, false ); | 456 | emit key( scan_uni&0xffff, scan, 0, true, false ); |
455 | emit key( scan_uni&0xffff, scan, 0, false, false ); | 457 | emit key( scan_uni&0xffff, scan, 0, false, false ); |
456 | } | 458 | } |
457 | 459 | ||
458 | void QIMPenInput::handleExtended( const QString &ex ) | 460 | void QIMPenInput::handleExtended( const QString &ex ) |
459 | { | 461 | { |
460 | if ( ex.find( "Select" ) == 0 ) { | 462 | if ( ex.find( "Select" ) == 0 ) { |
461 | QString set = ex.mid( 7 ); | 463 | QString set = ex.mid( 7 ); |
462 | qDebug( "Select new profile: %s", set.latin1() ); | 464 | odebug << "Select new profile: " << set.latin1() << oendl; |
463 | selectProfile( set ); | 465 | selectProfile( set ); |
464 | } | 466 | } |
465 | } | 467 | } |
466 | 468 | ||
467 | void QIMPenInput::help() | 469 | void QIMPenInput::help() |
468 | { | 470 | { |
469 | if ( helpDlg ) | 471 | if ( helpDlg ) |
470 | delete (HandwritingHelp*) helpDlg; | 472 | delete (HandwritingHelp*) helpDlg; |
471 | helpDlg = new HandwritingHelp( profile, 0, 0, WDestructiveClose ); | 473 | helpDlg = new HandwritingHelp( profile, 0, 0, WDestructiveClose ); |
472 | helpDlg->showMaximized(); | 474 | helpDlg->showMaximized(); |
473 | helpDlg->show(); | 475 | helpDlg->show(); |
474 | helpDlg->raise(); | 476 | helpDlg->raise(); |
475 | } | 477 | } |
476 | 478 | ||
477 | /*! | 479 | /*! |
478 | Open the setup dialog | 480 | Open the setup dialog |
479 | */ | 481 | */ |
480 | void QIMPenInput::setup() | 482 | void QIMPenInput::setup() |
481 | { | 483 | { |
482 | if ( !setupDlg ) { | 484 | if ( !setupDlg ) { |
483 | // We are working with our copy of the char sets here. | 485 | // We are working with our copy of the char sets here. |
484 | setupDlg = new QIMPenSetup( profile, 0, 0, TRUE ); | 486 | setupDlg = new QIMPenSetup( profile, 0, 0, TRUE ); |
485 | setupDlg->editor()->selectCharSet( profile->charSets().at(1) );// lower case? This is crap. | 487 | setupDlg->editor()->selectCharSet( profile->charSets().at(1) );// lower case? This is crap. |
486 | if ( qApp->desktop()->width() < 640 ) | 488 | if ( qApp->desktop()->width() < 640 ) |
487 | setupDlg->showMaximized(); | 489 | setupDlg->showMaximized(); |
488 | Global::hideInputMethod(); | 490 | Global::hideInputMethod(); |
489 | setupDlg->exec(); | 491 | setupDlg->exec(); |
490 | loadProfiles(); | 492 | loadProfiles(); |
491 | delete setupDlg; | 493 | delete setupDlg; |
492 | setupDlg = 0; | 494 | setupDlg = 0; |
493 | Global::showInputMethod(); | 495 | Global::showInputMethod(); |
494 | } else { | 496 | } else { |
495 | setupDlg->raise(); | 497 | setupDlg->raise(); |
496 | } | 498 | } |
497 | } | 499 | } |
498 | 500 | ||
499 | void QIMPenInput::backspace() | 501 | void QIMPenInput::backspace() |
500 | { | 502 | { |
501 | keypress( Qt::Key_Backspace << 16 ); | 503 | keypress( Qt::Key_Backspace << 16 ); |
502 | matcher->backspace(); | 504 | matcher->backspace(); |
503 | } | 505 | } |
504 | 506 | ||
505 | void QIMPenInput::enter() | 507 | void QIMPenInput::enter() |
506 | { | 508 | { |
507 | keypress( Qt::Key_Return << 16 ); | 509 | keypress( Qt::Key_Return << 16 ); |
508 | matcher->resetState(); | 510 | matcher->resetState(); |
509 | } | 511 | } |
510 | 512 | ||
diff --git a/inputmethods/handwriting/qimpenmatch.cpp b/inputmethods/handwriting/qimpenmatch.cpp index 0d3e25a..a0448b6 100644 --- a/inputmethods/handwriting/qimpenmatch.cpp +++ b/inputmethods/handwriting/qimpenmatch.cpp | |||
@@ -1,336 +1,337 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qtopia Environment. | 4 | ** This file is part of Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | 20 | ||
21 | #include "qimpenmatch.h" | 21 | #include "qimpenmatch.h" |
22 | 22 | ||
23 | #include <qpe/qdawg.h> | 23 | #include <qpe/qdawg.h> |
24 | #include <qpe/global.h> | 24 | #include <qpe/global.h> |
25 | 25 | ||
26 | #include <qapplication.h> | 26 | #include <qapplication.h> |
27 | #include <qtimer.h> | 27 | #include <qtimer.h> |
28 | #include <opie2/odebug.h> | ||
28 | 29 | ||
29 | #include <limits.h> | 30 | #include <limits.h> |
30 | 31 | ||
31 | #define ERROR_THRESHOLD 200000 | 32 | #define ERROR_THRESHOLD 200000 |
32 | #define LOOKAHEAD_ERROR 2500 | 33 | #define LOOKAHEAD_ERROR 2500 |
33 | //#define DEBUG_QIMPEN | 34 | //#define DEBUG_QIMPEN |
34 | 35 | ||
35 | QIMPenMatch::QIMPenMatch( QObject *parent, const char *name ) | 36 | QIMPenMatch::QIMPenMatch( QObject *parent, const char *name ) |
36 | : QObject( parent, name ) | 37 | : QObject( parent, name ) |
37 | { | 38 | { |
38 | strokes.setAutoDelete( TRUE ); | 39 | strokes.setAutoDelete( TRUE ); |
39 | wordChars.setAutoDelete( TRUE ); | 40 | wordChars.setAutoDelete( TRUE ); |
40 | wordMatches.setAutoDelete( TRUE ); | 41 | wordMatches.setAutoDelete( TRUE ); |
41 | 42 | ||
42 | multiTimer = new QTimer( this ); | 43 | multiTimer = new QTimer( this ); |
43 | connect( multiTimer, SIGNAL(timeout()), this, SLOT(endMulti()) ); | 44 | connect( multiTimer, SIGNAL(timeout()), this, SLOT(endMulti()) ); |
44 | 45 | ||
45 | prevMatchChar = 0; | 46 | prevMatchChar = 0; |
46 | prevMatchError = INT_MAX; | 47 | prevMatchError = INT_MAX; |
47 | charSet = 0; | 48 | charSet = 0; |
48 | multiCharSet = 0; | 49 | multiCharSet = 0; |
49 | multiTimeout = 500; | 50 | multiTimeout = 500; |
50 | canErase = FALSE; | 51 | canErase = FALSE; |
51 | doWordMatching = true; | 52 | doWordMatching = true; |
52 | } | 53 | } |
53 | 54 | ||
54 | QIMPenMatch::~QIMPenMatch() | 55 | QIMPenMatch::~QIMPenMatch() |
55 | { | 56 | { |
56 | } | 57 | } |
57 | 58 | ||
58 | void QIMPenMatch::setCharSet( QIMPenCharSet *cs ) | 59 | void QIMPenMatch::setCharSet( QIMPenCharSet *cs ) |
59 | { | 60 | { |
60 | charSet = cs; | 61 | charSet = cs; |
61 | } | 62 | } |
62 | 63 | ||
63 | void QIMPenMatch::beginStroke() | 64 | void QIMPenMatch::beginStroke() |
64 | { | 65 | { |
65 | multiTimer->stop(); | 66 | multiTimer->stop(); |
66 | } | 67 | } |
67 | 68 | ||
68 | void QIMPenMatch::strokeEntered( QIMPenStroke *st ) | 69 | void QIMPenMatch::strokeEntered( QIMPenStroke *st ) |
69 | { | 70 | { |
70 | #ifdef DEBUG_QIMPEN | 71 | #ifdef DEBUG_QIMPEN |
71 | qDebug( "---------- new stroke -------------" ); | 72 | odebug << "---------- new stroke -------------" << oendl; |
72 | #endif | 73 | #endif |
73 | strokes.append( new QIMPenStroke( *st ) ); | 74 | strokes.append( new QIMPenStroke( *st ) ); |
74 | 75 | ||
75 | QIMPenChar testChar; | 76 | QIMPenChar testChar; |
76 | QIMPenStrokeIterator it(strokes); | 77 | QIMPenStrokeIterator it(strokes); |
77 | for ( ; it.current(); ++it ) { | 78 | for ( ; it.current(); ++it ) { |
78 | testChar.addStroke( it.current() ); | 79 | testChar.addStroke( it.current() ); |
79 | } | 80 | } |
80 | 81 | ||
81 | QIMPenCharMatchList ml; | 82 | QIMPenCharMatchList ml; |
82 | if ( strokes.count() > 1 && multiCharSet ) { | 83 | if ( strokes.count() > 1 && multiCharSet ) { |
83 | #ifdef DEBUG_QIMPEN | 84 | #ifdef DEBUG_QIMPEN |
84 | qDebug( "Matching against multi set" ); | 85 | odebug << "Matching against multi set" << oendl; |
85 | #endif | 86 | #endif |
86 | ml = multiCharSet->match( &testChar ); | 87 | ml = multiCharSet->match( &testChar ); |
87 | } else { | 88 | } else { |
88 | #ifdef DEBUG_QIMPEN | 89 | #ifdef DEBUG_QIMPEN |
89 | qDebug( "Matching against single set" ); | 90 | odebug << "Matching against single set" << oendl; |
90 | #endif | 91 | #endif |
91 | ml = charSet->match( &testChar ); | 92 | ml = charSet->match( &testChar ); |
92 | } | 93 | } |
93 | 94 | ||
94 | processMatches( ml ); | 95 | processMatches( ml ); |
95 | } | 96 | } |
96 | 97 | ||
97 | void QIMPenMatch::processMatches( QIMPenCharMatchList &ml ) | 98 | void QIMPenMatch::processMatches( QIMPenCharMatchList &ml ) |
98 | { | 99 | { |
99 | #ifdef DEBUG_QIMPEN | 100 | #ifdef DEBUG_QIMPEN |
100 | qDebug( "Entering strokes.count() = %d", strokes.count() ); | 101 | odebug << "Entering strokes.count() = " << strokes.count() << oendl; |
101 | #endif | 102 | #endif |
102 | QIMPenCharMatch candidate1 = { INT_MAX, 0 }; | 103 | QIMPenCharMatch candidate1 = { INT_MAX, 0 }; |
103 | QIMPenCharMatch candidate2 = { INT_MAX, 0 }; | 104 | QIMPenCharMatch candidate2 = { INT_MAX, 0 }; |
104 | QIMPenCharMatchList ml2; | 105 | QIMPenCharMatchList ml2; |
105 | 106 | ||
106 | if ( ml.count() ) {//&& | 107 | if ( ml.count() ) {//&& |
107 | // ml.first().penChar->penStrokes().count() == strokes.count() ) { | 108 | // ml.first().penChar->penStrokes().count() == strokes.count() ) { |
108 | candidate1 = ml.first(); | 109 | candidate1 = ml.first(); |
109 | #ifdef DEBUG_QIMPEN | 110 | #ifdef DEBUG_QIMPEN |
110 | qDebug( QString("Candidate1 = %1").arg(QChar(candidate1.penChar->character())) ); | 111 | odebug << "Candidate1 = " << candidate1.penChar->character() << oendl; |
111 | #endif | 112 | #endif |
112 | } | 113 | } |
113 | 114 | ||
114 | if ( strokes.count() > 1 ) { | 115 | if ( strokes.count() > 1 ) { |
115 | // See if the last stroke can match a new character | 116 | // See if the last stroke can match a new character |
116 | QIMPenChar testChar; | 117 | QIMPenChar testChar; |
117 | QIMPenStroke *st = strokes.at(strokes.count()-1); | 118 | QIMPenStroke *st = strokes.at(strokes.count()-1); |
118 | testChar.addStroke( st ); | 119 | testChar.addStroke( st ); |
119 | ml2 = charSet->match( &testChar ); | 120 | ml2 = charSet->match( &testChar ); |
120 | if ( ml2.count() ) { | 121 | if ( ml2.count() ) { |
121 | candidate2 = ml2.first(); | 122 | candidate2 = ml2.first(); |
122 | #ifdef DEBUG_QIMPEN | 123 | #ifdef DEBUG_QIMPEN |
123 | qDebug( QString("Candidate2 = %1").arg(QChar(candidate2.penChar->character())) ); | 124 | odebug << "Candidate2 = " << candidate2.penChar->character() << oendl; |
124 | #endif | 125 | #endif |
125 | } | 126 | } |
126 | } | 127 | } |
127 | 128 | ||
128 | bool eraseLast = FALSE; | 129 | bool eraseLast = FALSE; |
129 | bool output = TRUE; | 130 | bool output = TRUE; |
130 | 131 | ||
131 | if ( candidate1.penChar && candidate2.penChar ) { | 132 | if ( candidate1.penChar && candidate2.penChar ) { |
132 | // Hmmm, a multi-stroke or a new character are both possible. | 133 | // Hmmm, a multi-stroke or a new character are both possible. |
133 | // Bias the multi-stroke case. | 134 | // Bias the multi-stroke case. |
134 | if ( QMAX(candidate2.error, prevMatchError)*3 < candidate1.error ) { | 135 | if ( QMAX(candidate2.error, prevMatchError)*3 < candidate1.error ) { |
135 | int i = strokes.count()-1; | 136 | int i = strokes.count()-1; |
136 | while ( i-- ) { | 137 | while ( i-- ) { |
137 | strokes.removeFirst(); | 138 | strokes.removeFirst(); |
138 | emit removeStroke(); | 139 | emit removeStroke(); |
139 | } | 140 | } |
140 | prevMatchChar = candidate2.penChar; | 141 | prevMatchChar = candidate2.penChar; |
141 | prevMatchError = candidate2.error; | 142 | prevMatchError = candidate2.error; |
142 | multiCharSet = charSet; | 143 | multiCharSet = charSet; |
143 | ml = ml2; | 144 | ml = ml2; |
144 | #ifdef DEBUG_QIMPEN | 145 | #ifdef DEBUG_QIMPEN |
145 | qDebug( "** Using Candidate2" ); | 146 | odebug << "** Using Candidate2" << oendl; |
146 | #endif | 147 | #endif |
147 | } else { | 148 | } else { |
148 | if ( (prevMatchChar->character() >> 16) != Qt::Key_Backspace && | 149 | if ( (prevMatchChar->character() >> 16) != Qt::Key_Backspace && |
149 | (prevMatchChar->character() >> 16) < QIMPenChar::ModeBase ) | 150 | (prevMatchChar->character() >> 16) < QIMPenChar::ModeBase ) |
150 | eraseLast = TRUE; | 151 | eraseLast = TRUE; |
151 | prevMatchChar = candidate1.penChar; | 152 | prevMatchChar = candidate1.penChar; |
152 | prevMatchError = candidate1.error; | 153 | prevMatchError = candidate1.error; |
153 | #ifdef DEBUG_QIMPEN | 154 | #ifdef DEBUG_QIMPEN |
154 | qDebug( "** Using Candidate1, with erase" ); | 155 | odebug << "** Using Candidate1, with erase" << oendl; |
155 | #endif | 156 | #endif |
156 | } | 157 | } |
157 | } else if ( candidate1.penChar ) { | 158 | } else if ( candidate1.penChar ) { |
158 | if ( strokes.count() != 1 ) | 159 | if ( strokes.count() != 1 ) |
159 | eraseLast = TRUE; | 160 | eraseLast = TRUE; |
160 | else | 161 | else |
161 | multiCharSet = charSet; | 162 | multiCharSet = charSet; |
162 | prevMatchChar = candidate1.penChar; | 163 | prevMatchChar = candidate1.penChar; |
163 | prevMatchError = candidate1.error; | 164 | prevMatchError = candidate1.error; |
164 | #ifdef DEBUG_QIMPEN | 165 | #ifdef DEBUG_QIMPEN |
165 | qDebug( "** Using Candidate1" ); | 166 | odebug << "** Using Candidate1" << oendl; |
166 | #endif | 167 | #endif |
167 | } else if ( candidate2.penChar ) { | 168 | } else if ( candidate2.penChar ) { |
168 | int i = strokes.count()-1; | 169 | int i = strokes.count()-1; |
169 | while ( i-- ) { | 170 | while ( i-- ) { |
170 | strokes.removeFirst(); | 171 | strokes.removeFirst(); |
171 | emit removeStroke(); | 172 | emit removeStroke(); |
172 | } | 173 | } |
173 | prevMatchChar = candidate2.penChar; | 174 | prevMatchChar = candidate2.penChar; |
174 | prevMatchError = candidate2.error; | 175 | prevMatchError = candidate2.error; |
175 | multiCharSet = charSet; | 176 | multiCharSet = charSet; |
176 | ml = ml2; | 177 | ml = ml2; |
177 | #ifdef DEBUG_QIMPEN | 178 | #ifdef DEBUG_QIMPEN |
178 | qDebug( "** Using Candidate2" ); | 179 | odebug << "** Using Candidate2" << oendl; |
179 | #endif | 180 | #endif |
180 | } else { | 181 | } else { |
181 | if ( !ml.count() ) { | 182 | if ( !ml.count() ) { |
182 | #ifdef DEBUG_QIMPEN | 183 | #ifdef DEBUG_QIMPEN |
183 | qDebug( "** Failed" ); | 184 | odebug << "** Failed" << oendl; |
184 | #endif | 185 | #endif |
185 | canErase = FALSE; | 186 | canErase = FALSE; |
186 | } else { | 187 | } else { |
187 | #ifdef DEBUG_QIMPEN | 188 | #ifdef DEBUG_QIMPEN |
188 | qDebug( "Need more strokes" ); | 189 | odebug << "Need more strokes" << oendl; |
189 | #endif | 190 | #endif |
190 | if ( strokes.count() == 1 ) | 191 | if ( strokes.count() == 1 ) |
191 | canErase = FALSE; | 192 | canErase = FALSE; |
192 | multiCharSet = charSet; | 193 | multiCharSet = charSet; |
193 | } | 194 | } |
194 | output = FALSE; | 195 | output = FALSE; |
195 | emit noMatch(); | 196 | emit noMatch(); |
196 | } | 197 | } |
197 | 198 | ||
198 | if ( eraseLast && canErase ) { | 199 | if ( eraseLast && canErase ) { |
199 | #ifdef DEBUG_QIMPEN | 200 | #ifdef DEBUG_QIMPEN |
200 | qDebug( "deleting last" ); | 201 | odebug << "deleting last" << oendl; |
201 | #endif | 202 | #endif |
202 | emit erase(); | 203 | emit erase(); |
203 | wordChars.removeLast(); | 204 | wordChars.removeLast(); |
204 | wordEntered.truncate( wordEntered.length() - 1 ); | 205 | wordEntered.truncate( wordEntered.length() - 1 ); |
205 | } | 206 | } |
206 | 207 | ||
207 | if ( output ) { | 208 | if ( output ) { |
208 | emit matchedCharacters( ml ); | 209 | emit matchedCharacters( ml ); |
209 | uint code = prevMatchChar->character() >> 16; | 210 | uint code = prevMatchChar->character() >> 16; |
210 | if ( code < QIMPenChar::ModeBase ) { | 211 | if ( code < QIMPenChar::ModeBase ) { |
211 | updateWordMatch( ml ); | 212 | updateWordMatch( ml ); |
212 | emit keypress( prevMatchChar->character() ); | 213 | emit keypress( prevMatchChar->character() ); |
213 | } | 214 | } |
214 | canErase = TRUE; | 215 | canErase = TRUE; |
215 | } | 216 | } |
216 | 217 | ||
217 | if ( strokes.count() ) | 218 | if ( strokes.count() ) |
218 | multiTimer->start( multiTimeout, TRUE ); | 219 | multiTimer->start( multiTimeout, TRUE ); |
219 | } | 220 | } |
220 | 221 | ||
221 | void QIMPenMatch::updateWordMatch( QIMPenCharMatchList &ml ) | 222 | void QIMPenMatch::updateWordMatch( QIMPenCharMatchList &ml ) |
222 | { | 223 | { |
223 | if ( !ml.count() || !doWordMatching ) | 224 | if ( !ml.count() || !doWordMatching ) |
224 | return; | 225 | return; |
225 | int ch = ml.first().penChar->character(); | 226 | int ch = ml.first().penChar->character(); |
226 | QChar qch( ch ); | 227 | QChar qch( ch ); |
227 | int code = ch >> 16; | 228 | int code = ch >> 16; |
228 | if ( qch.isPunct() || qch.isSpace() || | 229 | if ( qch.isPunct() || qch.isSpace() || |
229 | code == Qt::Key_Enter || code == Qt::Key_Return || | 230 | code == Qt::Key_Enter || code == Qt::Key_Return || |
230 | code == Qt::Key_Tab || code == Qt::Key_Escape ) { | 231 | code == Qt::Key_Tab || code == Qt::Key_Escape ) { |
231 | //qDebug( "Word Matching: Clearing word" ); | 232 | //odebug << "Word Matching: Clearing word" << oendl; |
232 | wordChars.clear(); | 233 | wordChars.clear(); |
233 | wordMatches.clear(); | 234 | wordMatches.clear(); |
234 | wordEntered = QString(); | 235 | wordEntered = QString(); |
235 | } else if ( code == Qt::Key_Backspace ) { | 236 | } else if ( code == Qt::Key_Backspace ) { |
236 | //qDebug( "Word Matching: Handle backspace" ); | 237 | //odebug << "Word Matching: Handle backspace" << oendl; |
237 | wordChars.removeLast(); | 238 | wordChars.removeLast(); |
238 | wordEntered.truncate( wordEntered.length() - 1 ); | 239 | wordEntered.truncate( wordEntered.length() - 1 ); |
239 | matchWords(); | 240 | matchWords(); |
240 | } else { | 241 | } else { |
241 | QIMPenChar *matchCh; | 242 | QIMPenChar *matchCh; |
242 | 243 | ||
243 | wordChars.append( new QIMPenCharMatchList() ); | 244 | wordChars.append( new QIMPenCharMatchList() ); |
244 | wordEntered += ml.first().penChar->character(); | 245 | wordEntered += ml.first().penChar->character(); |
245 | 246 | ||
246 | QIMPenCharMatchList::Iterator it; | 247 | QIMPenCharMatchList::Iterator it; |
247 | for ( it = ml.begin(); it != ml.end(); ++it ) { | 248 | for ( it = ml.begin(); it != ml.end(); ++it ) { |
248 | matchCh = (*it).penChar; | 249 | matchCh = (*it).penChar; |
249 | 250 | ||
250 | if ( matchCh->penStrokes().count() == strokes.count() ) { | 251 | if ( matchCh->penStrokes().count() == strokes.count() ) { |
251 | QChar ch(matchCh->character()); | 252 | QChar ch(matchCh->character()); |
252 | if ( !ch.isPunct() && !ch.isSpace() ) { | 253 | if ( !ch.isPunct() && !ch.isSpace() ) { |
253 | wordChars.last()->append( QIMPenCharMatch( (*it) ) ); | 254 | wordChars.last()->append( QIMPenCharMatch( (*it) ) ); |
254 | } | 255 | } |
255 | } | 256 | } |
256 | } | 257 | } |
257 | matchWords(); | 258 | matchWords(); |
258 | } | 259 | } |
259 | if ( !wordMatches.count() || wordMatches.getFirst()->word != wordEntered ) | 260 | if ( !wordMatches.count() || wordMatches.getFirst()->word != wordEntered ) |
260 | wordMatches.prepend( new MatchWord( wordEntered, 0 ) ); | 261 | wordMatches.prepend( new MatchWord( wordEntered, 0 ) ); |
261 | emit matchedWords( wordMatches ); | 262 | emit matchedWords( wordMatches ); |
262 | } | 263 | } |
263 | 264 | ||
264 | void QIMPenMatch::matchWords() | 265 | void QIMPenMatch::matchWords() |
265 | { | 266 | { |
266 | if ( wordEntered.length() > 0 ) { | 267 | if ( wordEntered.length() > 0 ) { |
267 | // more leaniency if we don't have many matches | 268 | // more leaniency if we don't have many matches |
268 | if ( badMatches < 200 ) | 269 | if ( badMatches < 200 ) |
269 | errorThreshold += (200 - badMatches) * 100; | 270 | errorThreshold += (200 - badMatches) * 100; |
270 | } else | 271 | } else |
271 | errorThreshold = ERROR_THRESHOLD; | 272 | errorThreshold = ERROR_THRESHOLD; |
272 | wordMatches.clear(); | 273 | wordMatches.clear(); |
273 | goodMatches = 0; | 274 | goodMatches = 0; |
274 | badMatches = 0; | 275 | badMatches = 0; |
275 | if ( wordChars.count() > 0 ) { | 276 | if ( wordChars.count() > 0 ) { |
276 | maxGuess = (int)wordChars.count() * 2; | 277 | maxGuess = (int)wordChars.count() * 2; |
277 | if ( maxGuess < 3 ) | 278 | if ( maxGuess < 3 ) |
278 | maxGuess = 3; | 279 | maxGuess = 3; |
279 | QString str; | 280 | QString str; |
280 | scanDict( Global::fixedDawg().root(), 0, str, 0 ); | 281 | scanDict( Global::fixedDawg().root(), 0, str, 0 ); |
281 | /* | 282 | /* |
282 | QListIterator<MatchWord> it( wordMatches); | 283 | QListIterator<MatchWord> it( wordMatches); |
283 | for ( ; it.current(); ++it ) { | 284 | for ( ; it.current(); ++it ) { |
284 | qDebug( QString("Match word: %1").arg(it.current()->word) ); | 285 | odebug << "Match word: " << it.current()->word << oendl; |
285 | } | 286 | } |
286 | */ | 287 | */ |
287 | } | 288 | } |
288 | //qDebug( "Possibles: Good %d, total %d", goodMatches, wordMatches.count() ); | 289 | //odebug << "Possibles: Good " << goodMatches << ", total " << wordMatches.count() << oendl; |
289 | wordMatches.sort(); | 290 | wordMatches.sort(); |
290 | } | 291 | } |
291 | 292 | ||
292 | void QIMPenMatch::scanDict( const QDawg::Node* n, int ipos, const QString& str, int error ) | 293 | void QIMPenMatch::scanDict( const QDawg::Node* n, int ipos, const QString& str, int error ) |
293 | { | 294 | { |
294 | if ( !n ) | 295 | if ( !n ) |
295 | return; | 296 | return; |
296 | if ( error / (ipos+1) > errorThreshold ) | 297 | if ( error / (ipos+1) > errorThreshold ) |
297 | return; | 298 | return; |
298 | 299 | ||
299 | while (n) { | 300 | while (n) { |
300 | if ( goodMatches > 20 ) | 301 | if ( goodMatches > 20 ) |
301 | break; | 302 | break; |
302 | if ( ipos < (int)wordChars.count() ) { | 303 | if ( ipos < (int)wordChars.count() ) { |
303 | int i; | 304 | int i; |
304 | QChar testCh = QChar(n->letter()); | 305 | QChar testCh = QChar(n->letter()); |
305 | QIMPenCharMatchList::Iterator it; | 306 | QIMPenCharMatchList::Iterator it; |
306 | for ( i = 0, it = wordChars.at(ipos)->begin(); | 307 | for ( i = 0, it = wordChars.at(ipos)->begin(); |
307 | it != wordChars.at(ipos)->end() && i < 8; ++it, i++ ) { | 308 | it != wordChars.at(ipos)->end() && i < 8; ++it, i++ ) { |
308 | QChar ch( (*it).penChar->character() ); | 309 | QChar ch( (*it).penChar->character() ); |
309 | if ( ch == testCh || ( !ipos && ch.lower() == testCh.lower() ) ) { | 310 | if ( ch == testCh || ( !ipos && ch.lower() == testCh.lower() ) ) { |
310 | int newerr = error + (*it).error; | 311 | int newerr = error + (*it).error; |
311 | if ( testCh.category() == QChar::Letter_Uppercase ) | 312 | if ( testCh.category() == QChar::Letter_Uppercase ) |
312 | ch = testCh; | 313 | ch = testCh; |
313 | QString newstr( str + ch ); | 314 | QString newstr( str + ch ); |
314 | if ( n->isWord() && ipos == (int)wordChars.count() - 1 ) { | 315 | if ( n->isWord() && ipos == (int)wordChars.count() - 1 ) { |
315 | wordMatches.append( new MatchWord( newstr, newerr ) ); | 316 | wordMatches.append( new MatchWord( newstr, newerr ) ); |
316 | goodMatches++; | 317 | goodMatches++; |
317 | } | 318 | } |
318 | scanDict( n->jump(), ipos+1, newstr, newerr ); | 319 | scanDict( n->jump(), ipos+1, newstr, newerr ); |
319 | } | 320 | } |
320 | } | 321 | } |
321 | } else if ( badMatches < 200 && ipos < maxGuess ) { | 322 | } else if ( badMatches < 200 && ipos < maxGuess ) { |
322 | int d = ipos - wordChars.count(); | 323 | int d = ipos - wordChars.count(); |
323 | int newerr = error + ERROR_THRESHOLD + LOOKAHEAD_ERROR*d; | 324 | int newerr = error + ERROR_THRESHOLD + LOOKAHEAD_ERROR*d; |
324 | QString newstr( str + n->letter() ); | 325 | QString newstr( str + n->letter() ); |
325 | if ( n->isWord() ) { | 326 | if ( n->isWord() ) { |
326 | wordMatches.append( new MatchWord( newstr, newerr ) ); | 327 | wordMatches.append( new MatchWord( newstr, newerr ) ); |
327 | badMatches++; | 328 | badMatches++; |
328 | } | 329 | } |
329 | scanDict( n->jump(), ipos+1, newstr, newerr ); | 330 | scanDict( n->jump(), ipos+1, newstr, newerr ); |
330 | } | 331 | } |
331 | n = n->next(); | 332 | n = n->next(); |
332 | } | 333 | } |
333 | } | 334 | } |
334 | 335 | ||
335 | void QIMPenMatch::backspace() | 336 | void QIMPenMatch::backspace() |
336 | { | 337 | { |
diff --git a/inputmethods/handwriting/qimpenstroke.cpp b/inputmethods/handwriting/qimpenstroke.cpp index 3567d6d..14e435a 100644 --- a/inputmethods/handwriting/qimpenstroke.cpp +++ b/inputmethods/handwriting/qimpenstroke.cpp | |||
@@ -1,100 +1,101 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qtopia Environment. | 4 | ** This file is part of Qtopia Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | 20 | ||
21 | #include <qfile.h> | 21 | #include <qfile.h> |
22 | #include <qtl.h> | 22 | #include <qtl.h> |
23 | #include <math.h> | 23 | #include <math.h> |
24 | #include <limits.h> | 24 | #include <limits.h> |
25 | #include <qdatastream.h> | 25 | #include <qdatastream.h> |
26 | #include "qimpenstroke.h" | 26 | #include "qimpenstroke.h" |
27 | #include "opie2/odebug.h" | ||
27 | 28 | ||
28 | #define QIMPEN_CORRELATION_POINTS 25 | 29 | #define QIMPEN_CORRELATION_POINTS 25 |
29 | //#define DEBUG_QIMPEN | 30 | //#define DEBUG_QIMPEN |
30 | 31 | ||
31 | /*! | 32 | /*! |
32 | \class QIMPenStroke qimpenstroke.h | 33 | \class QIMPenStroke qimpenstroke.h |
33 | 34 | ||
34 | Handles a single stroke. Can calculate closeness of match to | 35 | Handles a single stroke. Can calculate closeness of match to |
35 | another stroke. | 36 | another stroke. |
36 | */ | 37 | */ |
37 | 38 | ||
38 | QIMPenStroke::QIMPenStroke() | 39 | QIMPenStroke::QIMPenStroke() |
39 | { | 40 | { |
40 | } | 41 | } |
41 | 42 | ||
42 | QIMPenStroke::QIMPenStroke( const QIMPenStroke &st ) | 43 | QIMPenStroke::QIMPenStroke( const QIMPenStroke &st ) |
43 | { | 44 | { |
44 | startPoint = st.startPoint; | 45 | startPoint = st.startPoint; |
45 | lastPoint = st.lastPoint; | 46 | lastPoint = st.lastPoint; |
46 | links = st.links.copy(); | 47 | links = st.links.copy(); |
47 | } | 48 | } |
48 | 49 | ||
49 | QIMPenStroke &QIMPenStroke::operator=( const QIMPenStroke &s ) | 50 | QIMPenStroke &QIMPenStroke::operator=( const QIMPenStroke &s ) |
50 | { | 51 | { |
51 | clear(); | 52 | clear(); |
52 | //qDebug( "copy strokes %d", s.links.count() ); | 53 | //odebug << "copy strokes " << s.links.count() << oendl; |
53 | startPoint = s.startPoint; | 54 | startPoint = s.startPoint; |
54 | lastPoint = s.lastPoint; | 55 | lastPoint = s.lastPoint; |
55 | links = s.links.copy(); | 56 | links = s.links.copy(); |
56 | 57 | ||
57 | return *this; | 58 | return *this; |
58 | } | 59 | } |
59 | 60 | ||
60 | void QIMPenStroke::clear() | 61 | void QIMPenStroke::clear() |
61 | { | 62 | { |
62 | startPoint = QPoint(0,0); | 63 | startPoint = QPoint(0,0); |
63 | lastPoint = QPoint( 0, 0 ); | 64 | lastPoint = QPoint( 0, 0 ); |
64 | links.resize( 0 ); | 65 | links.resize( 0 ); |
65 | tsig.resize( 0 ); | 66 | tsig.resize( 0 ); |
66 | dsig.resize( 0 ); | 67 | dsig.resize( 0 ); |
67 | asig.resize( 0 ); | 68 | asig.resize( 0 ); |
68 | } | 69 | } |
69 | 70 | ||
70 | /*! | 71 | /*! |
71 | Begin inputting a new stroke. | 72 | Begin inputting a new stroke. |
72 | */ | 73 | */ |
73 | void QIMPenStroke::beginInput( QPoint p ) | 74 | void QIMPenStroke::beginInput( QPoint p ) |
74 | { | 75 | { |
75 | clear(); | 76 | clear(); |
76 | startPoint = p; | 77 | startPoint = p; |
77 | bounding = QRect(); | 78 | bounding = QRect(); |
78 | internalAddPoint( p ); | 79 | internalAddPoint( p ); |
79 | } | 80 | } |
80 | 81 | ||
81 | /*! | 82 | /*! |
82 | Add a point to the stroke's shape. | 83 | Add a point to the stroke's shape. |
83 | Returns TRUE if the point was successfully added. | 84 | Returns TRUE if the point was successfully added. |
84 | */ | 85 | */ |
85 | bool QIMPenStroke::addPoint( QPoint p ) | 86 | bool QIMPenStroke::addPoint( QPoint p ) |
86 | { | 87 | { |
87 | if ( links.count() > 500 ) // sanity check (that the user is sane). | 88 | if ( links.count() > 500 ) // sanity check (that the user is sane). |
88 | return FALSE; | 89 | return FALSE; |
89 | 90 | ||
90 | int dx = p.x() - lastPoint.x(); | 91 | int dx = p.x() - lastPoint.x(); |
91 | int dy = p.y() - lastPoint.y(); | 92 | int dy = p.y() - lastPoint.y(); |
92 | if ( QABS( dx ) > 1 || QABS( dy ) > 1 ) { | 93 | if ( QABS( dx ) > 1 || QABS( dy ) > 1 ) { |
93 | // The point is not adjacent to the previous point, so we fill | 94 | // The point is not adjacent to the previous point, so we fill |
94 | // in with a straight line. Some kind of non-linear | 95 | // in with a straight line. Some kind of non-linear |
95 | // interpolation might be better. | 96 | // interpolation might be better. |
96 | int x = lastPoint.x(); | 97 | int x = lastPoint.x(); |
97 | int y = lastPoint.y(); | 98 | int y = lastPoint.y(); |
98 | int ix = 1; | 99 | int ix = 1; |
99 | int iy = 1; | 100 | int iy = 1; |
100 | if ( dx < 0 ) { | 101 | if ( dx < 0 ) { |
@@ -104,195 +105,195 @@ bool QIMPenStroke::addPoint( QPoint p ) | |||
104 | if ( dy < 0 ) { | 105 | if ( dy < 0 ) { |
105 | iy = -1; | 106 | iy = -1; |
106 | dy = -dy; | 107 | dy = -dy; |
107 | } | 108 | } |
108 | int d = 0; | 109 | int d = 0; |
109 | if ( dx < dy ) { | 110 | if ( dx < dy ) { |
110 | d = dx; | 111 | d = dx; |
111 | do { | 112 | do { |
112 | y += iy; | 113 | y += iy; |
113 | d += dx; | 114 | d += dx; |
114 | if ( d > dy ) { | 115 | if ( d > dy ) { |
115 | x += ix; | 116 | x += ix; |
116 | d -= dy; | 117 | d -= dy; |
117 | } | 118 | } |
118 | internalAddPoint( QPoint( x, y ) ); | 119 | internalAddPoint( QPoint( x, y ) ); |
119 | } while ( y != p.y() ); | 120 | } while ( y != p.y() ); |
120 | } else { | 121 | } else { |
121 | d = dy; | 122 | d = dy; |
122 | do { | 123 | do { |
123 | x += ix; | 124 | x += ix; |
124 | d += dy; | 125 | d += dy; |
125 | if ( d > dx ) { | 126 | if ( d > dx ) { |
126 | y += iy; | 127 | y += iy; |
127 | d -= dx; | 128 | d -= dx; |
128 | } | 129 | } |
129 | internalAddPoint( QPoint( x, y ) ); | 130 | internalAddPoint( QPoint( x, y ) ); |
130 | } while ( x != p.x() ); | 131 | } while ( x != p.x() ); |
131 | } | 132 | } |
132 | } else { | 133 | } else { |
133 | internalAddPoint( p ); | 134 | internalAddPoint( p ); |
134 | } | 135 | } |
135 | 136 | ||
136 | return TRUE; | 137 | return TRUE; |
137 | } | 138 | } |
138 | 139 | ||
139 | /*! | 140 | /*! |
140 | Finish inputting a stroke. | 141 | Finish inputting a stroke. |
141 | */ | 142 | */ |
142 | void QIMPenStroke::endInput() | 143 | void QIMPenStroke::endInput() |
143 | { | 144 | { |
144 | if ( links.count() < 3 ) { | 145 | if ( links.count() < 3 ) { |
145 | QIMPenGlyphLink gl; | 146 | QIMPenGlyphLink gl; |
146 | links.resize(1); | 147 | links.resize(1); |
147 | gl.dx = 1; | 148 | gl.dx = 1; |
148 | gl.dy = 0; | 149 | gl.dy = 0; |
149 | links[0] = gl; | 150 | links[0] = gl; |
150 | } | 151 | } |
151 | 152 | ||
152 | //qDebug("Points: %d", links.count() ); | 153 | //odebug << "Points: " << links.count() << oendl; |
153 | } | 154 | } |
154 | 155 | ||
155 | /*! | 156 | /*! |
156 | Return an indicator of the closeness of this stroke to \a pen. | 157 | Return an indicator of the closeness of this stroke to \a pen. |
157 | Lower value is better. | 158 | Lower value is better. |
158 | */ | 159 | */ |
159 | unsigned int QIMPenStroke::match( QIMPenStroke *pen ) | 160 | unsigned int QIMPenStroke::match( QIMPenStroke *pen ) |
160 | { | 161 | { |
161 | double lratio; | 162 | double lratio; |
162 | 163 | ||
163 | if ( links.count() > pen->links.count() ) | 164 | if ( links.count() > pen->links.count() ) |
164 | lratio = (links.count()+2) / (pen->links.count()+2); | 165 | lratio = (links.count()+2) / (pen->links.count()+2); |
165 | else | 166 | else |
166 | lratio = (pen->links.count()+2) / (links.count()+2); | 167 | lratio = (pen->links.count()+2) / (links.count()+2); |
167 | 168 | ||
168 | lratio -= 1.0; | 169 | lratio -= 1.0; |
169 | 170 | ||
170 | if ( lratio > 2.0 ) { | 171 | if ( lratio > 2.0 ) { |
171 | #ifdef DEBUG_QIMPEN | 172 | #ifdef DEBUG_QIMPEN |
172 | qDebug( "stroke length too different" ); | 173 | odebug << "stroke length too different" << oendl; |
173 | #endif | 174 | #endif |
174 | return 400000; | 175 | return 400000; |
175 | } | 176 | } |
176 | 177 | ||
177 | createSignatures(); | 178 | createSignatures(); |
178 | pen->createSignatures(); | 179 | pen->createSignatures(); |
179 | 180 | ||
180 | // Starting point offset | 181 | // Starting point offset |
181 | int vdiff = QABS(startPoint.y() - pen->startPoint.y()); | 182 | int vdiff = QABS(startPoint.y() - pen->startPoint.y()); |
182 | 183 | ||
183 | // Insanely offset? | 184 | // Insanely offset? |
184 | if ( vdiff > 18 ) { | 185 | if ( vdiff > 18 ) { |
185 | return 400000; | 186 | return 400000; |
186 | } | 187 | } |
187 | 188 | ||
188 | vdiff -= 4; | 189 | vdiff -= 4; |
189 | if ( vdiff < 0 ) | 190 | if ( vdiff < 0 ) |
190 | vdiff = 0; | 191 | vdiff = 0; |
191 | 192 | ||
192 | // Ending point offset | 193 | // Ending point offset |
193 | int evdiff = QABS(lastPoint.y() - pen->lastPoint.y()); | 194 | int evdiff = QABS(lastPoint.y() - pen->lastPoint.y()); |
194 | // Insanely offset? | 195 | // Insanely offset? |
195 | if ( evdiff > 20 ) { | 196 | if ( evdiff > 20 ) { |
196 | return 400000; | 197 | return 400000; |
197 | } | 198 | } |
198 | 199 | ||
199 | evdiff -= 5; | 200 | evdiff -= 5; |
200 | if ( evdiff < 0 ) | 201 | if ( evdiff < 0 ) |
201 | evdiff = 0; | 202 | evdiff = 0; |
202 | 203 | ||
203 | // do a correlation with the three available signatures. | 204 | // do a correlation with the three available signatures. |
204 | int err1 = INT_MAX; | 205 | int err1 = INT_MAX; |
205 | int err2 = INT_MAX; | 206 | int err2 = INT_MAX; |
206 | int err3 = INT_MAX; | 207 | int err3 = INT_MAX; |
207 | 208 | ||
208 | // base has extra points at the start and end to enable | 209 | // base has extra points at the start and end to enable |
209 | // correlation of a sliding window with the pen supplied. | 210 | // correlation of a sliding window with the pen supplied. |
210 | QArray<int> base = createBase( tsig, 2 ); | 211 | QArray<int> base = createBase( tsig, 2 ); |
211 | for ( int i = 0; i < 4; i++ ) { | 212 | for ( int i = 0; i < 4; i++ ) { |
212 | int e = calcError( base, pen->tsig, i, TRUE ); | 213 | int e = calcError( base, pen->tsig, i, TRUE ); |
213 | if ( e < err1 ) | 214 | if ( e < err1 ) |
214 | err1 = e; | 215 | err1 = e; |
215 | } | 216 | } |
216 | if ( err1 > 40 ) { // no need for more matching | 217 | if ( err1 > 40 ) { // no need for more matching |
217 | #ifdef DEBUG_QIMPEN | 218 | #ifdef DEBUG_QIMPEN |
218 | qDebug( "tsig too great: %d", err1 ); | 219 | odebug << "tsig too great: " << err1 << oendl; |
219 | #endif | 220 | #endif |
220 | return 400000; | 221 | return 400000; |
221 | } | 222 | } |
222 | 223 | ||
223 | // maybe a sliding window is worthwhile for these too. | 224 | // maybe a sliding window is worthwhile for these too. |
224 | err2 = calcError( dsig, pen->dsig, 0, FALSE ); | 225 | err2 = calcError( dsig, pen->dsig, 0, FALSE ); |
225 | if ( err2 > 100 ) { | 226 | if ( err2 > 100 ) { |
226 | #ifdef DEBUG_QIMPEN | 227 | #ifdef DEBUG_QIMPEN |
227 | qDebug( "dsig too great: %d", err2 ); | 228 | odebug << "dsig too great: " << err2 << oendl; |
228 | #endif | 229 | #endif |
229 | return 400000; | 230 | return 400000; |
230 | } | 231 | } |
231 | 232 | ||
232 | err3 = calcError( asig, pen->asig, 0, TRUE ); | 233 | err3 = calcError( asig, pen->asig, 0, TRUE ); |
233 | if ( err3 > 60 ) { | 234 | if ( err3 > 60 ) { |
234 | #ifdef DEBUG_QIMPEN | 235 | #ifdef DEBUG_QIMPEN |
235 | qDebug( "asig too great: %d", err3 ); | 236 | odebug << "asig too great: " << err3 << oendl; |
236 | #endif | 237 | #endif |
237 | return 400000; | 238 | return 400000; |
238 | } | 239 | } |
239 | 240 | ||
240 | // Some magic numbers here - the addition reduces the weighting of | 241 | // Some magic numbers here - the addition reduces the weighting of |
241 | // the error and compensates for the different error scales. I | 242 | // the error and compensates for the different error scales. I |
242 | // consider the tangent signature to be the best indicator, so it | 243 | // consider the tangent signature to be the best indicator, so it |
243 | // has the most weight. This ain't rocket science. | 244 | // has the most weight. This ain't rocket science. |
244 | // Basically, these numbers are the tuning factors. | 245 | // Basically, these numbers are the tuning factors. |
245 | unsigned int err = (err1+1) * ( err2 + 60 ) * ( err3 + 20 ) + | 246 | unsigned int err = (err1+1) * ( err2 + 60 ) * ( err3 + 20 ) + |
246 | vdiff * 1000 + evdiff * 500 + | 247 | vdiff * 1000 + evdiff * 500 + |
247 | (unsigned int)(lratio * 5000.0); | 248 | (unsigned int)(lratio * 5000.0); |
248 | 249 | ||
249 | #ifdef DEBUG_QIMPEN | 250 | #ifdef DEBUG_QIMPEN |
250 | qDebug( "err %d ( %d, %d, %d, %d)", err, err1, err2, err3, vdiff ); | 251 | odebug << "err " << err << "( " << err1 << ", " << err2 << ", " << err3 << ", " << vdiff << oendl; |
251 | #endif | 252 | #endif |
252 | 253 | ||
253 | return err; | 254 | return err; |
254 | } | 255 | } |
255 | 256 | ||
256 | /*! | 257 | /*! |
257 | Return the bounding rect of this stroke. | 258 | Return the bounding rect of this stroke. |
258 | */ | 259 | */ |
259 | QRect QIMPenStroke::boundingRect() | 260 | QRect QIMPenStroke::boundingRect() |
260 | { | 261 | { |
261 | if ( !bounding.isValid() ) { | 262 | if ( !bounding.isValid() ) { |
262 | int x = startPoint.x(); | 263 | int x = startPoint.x(); |
263 | int y = startPoint.y(); | 264 | int y = startPoint.y(); |
264 | bounding = QRect( x, y, 1, 1 ); | 265 | bounding = QRect( x, y, 1, 1 ); |
265 | 266 | ||
266 | for ( unsigned i = 0; i < links.count(); i++ ) { | 267 | for ( unsigned i = 0; i < links.count(); i++ ) { |
267 | x += links[i].dx; | 268 | x += links[i].dx; |
268 | y += links[i].dy; | 269 | y += links[i].dy; |
269 | if ( x < bounding.left() ) | 270 | if ( x < bounding.left() ) |
270 | bounding.setLeft( x ); | 271 | bounding.setLeft( x ); |
271 | if ( x > bounding.right() ) | 272 | if ( x > bounding.right() ) |
272 | bounding.setRight( x ); | 273 | bounding.setRight( x ); |
273 | if ( y < bounding.top() ) | 274 | if ( y < bounding.top() ) |
274 | bounding.setTop( y ); | 275 | bounding.setTop( y ); |
275 | if ( y > bounding.bottom() ) | 276 | if ( y > bounding.bottom() ) |
276 | bounding.setBottom( y ); | 277 | bounding.setBottom( y ); |
277 | } | 278 | } |
278 | } | 279 | } |
279 | 280 | ||
280 | return bounding; | 281 | return bounding; |
281 | } | 282 | } |
282 | 283 | ||
283 | 284 | ||
284 | /*! | 285 | /*! |
285 | Perform a correlation of the supplied arrays. \a base should have | 286 | Perform a correlation of the supplied arrays. \a base should have |
286 | win.count() + 2 * off points to enable sliding \a win over the | 287 | win.count() + 2 * off points to enable sliding \a win over the |
287 | \a base data. If \a t is TRUE, the comparison takes into account | 288 | \a base data. If \a t is TRUE, the comparison takes into account |
288 | the circular nature of the angular data. | 289 | the circular nature of the angular data. |
289 | Returns the best (lowest error) match. | 290 | Returns the best (lowest error) match. |
290 | */ | 291 | */ |
291 | 292 | ||
292 | int QIMPenStroke::calcError( const QArray<int> &base, | 293 | int QIMPenStroke::calcError( const QArray<int> &base, |
293 | const QArray<int> &win, int off, bool t ) | 294 | const QArray<int> &win, int off, bool t ) |
294 | { | 295 | { |
295 | int err = 0; | 296 | int err = 0; |
296 | 297 | ||
297 | for ( unsigned i = 0; i < win.count(); i++ ) { | 298 | for ( unsigned i = 0; i < win.count(); i++ ) { |
298 | int d = QABS( base[i+off] - win[i] ); | 299 | int d = QABS( base[i+off] - win[i] ); |
diff --git a/inputmethods/handwriting/qimpenwordpick.cpp b/inputmethods/handwriting/qimpenwordpick.cpp index 8ee103d..39745c6 100644 --- a/inputmethods/handwriting/qimpenwordpick.cpp +++ b/inputmethods/handwriting/qimpenwordpick.cpp | |||
@@ -59,55 +59,55 @@ int QIMPenWordPick::onWord( QPoint p ) | |||
59 | if ( x + w > width() ) | 59 | if ( x + w > width() ) |
60 | break; | 60 | break; |
61 | if ( p.x() > x-2 && p.x() < x + w + 2 ) | 61 | if ( p.x() > x-2 && p.x() < x + w + 2 ) |
62 | return idx; | 62 | return idx; |
63 | x += w + 5; | 63 | x += w + 5; |
64 | if ( !idx ) | 64 | if ( !idx ) |
65 | x += 3; | 65 | x += 3; |
66 | idx++; | 66 | idx++; |
67 | } | 67 | } |
68 | 68 | ||
69 | return -1; | 69 | return -1; |
70 | } | 70 | } |
71 | 71 | ||
72 | void QIMPenWordPick::paintEvent( QPaintEvent * ) | 72 | void QIMPenWordPick::paintEvent( QPaintEvent * ) |
73 | { | 73 | { |
74 | QPainter p(this); | 74 | QPainter p(this); |
75 | int x = 2; | 75 | int x = 2; |
76 | int h = p.fontMetrics().ascent() + 1; | 76 | int h = p.fontMetrics().ascent() + 1; |
77 | int idx = 0; | 77 | int idx = 0; |
78 | for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) { | 78 | for ( QStringList::Iterator it = words.begin(); it != words.end(); ++it ) { |
79 | QString word = *it; | 79 | QString word = *it; |
80 | int w = p.fontMetrics().width( word ); | 80 | int w = p.fontMetrics().width( word ); |
81 | if ( x + w > width() ) | 81 | if ( x + w > width() ) |
82 | break; | 82 | break; |
83 | if ( idx == clickWord ) { | 83 | if ( idx == clickWord ) { |
84 | p.fillRect( x, 0, w, height(), black ); | 84 | p.fillRect( x, 0, w, height(), black ); |
85 | p.setPen( white ); | 85 | p.setPen( white ); |
86 | } else { | 86 | } else { |
87 | p.setPen( colorGroup().text() ); | 87 | p.setPen( colorGroup().text() ); |
88 | } | 88 | } |
89 | p.drawText( x, h, word ); | 89 | p.drawText( x, h, word ); |
90 | x += w + 5; | 90 | x += w + 5; |
91 | if ( !idx ) | 91 | if ( !idx ) |
92 | x += 3; | 92 | x += 3; |
93 | idx++; | 93 | idx++; |
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | void QIMPenWordPick::mousePressEvent( QMouseEvent *e ) | 97 | void QIMPenWordPick::mousePressEvent( QMouseEvent *e ) |
98 | { | 98 | { |
99 | clickWord = onWord( e->pos() ); | 99 | clickWord = onWord( e->pos() ); |
100 | repaint(); | 100 | repaint(); |
101 | } | 101 | } |
102 | 102 | ||
103 | void QIMPenWordPick::mouseReleaseEvent( QMouseEvent *e ) | 103 | void QIMPenWordPick::mouseReleaseEvent( QMouseEvent *e ) |
104 | { | 104 | { |
105 | int wordIdx = onWord( e->pos() ); | 105 | int wordIdx = onWord( e->pos() ); |
106 | if ( wordIdx >= 0 && wordIdx == clickWord ) { | 106 | if ( wordIdx >= 0 && wordIdx == clickWord ) { |
107 | //qDebug( "Clicked %s", words[wordIdx].latin1() ); | 107 | //odebug << "Clicked " << words[wordIdx].latin1() << oendl; |
108 | emit wordClicked( words[wordIdx] ); | 108 | emit wordClicked( words[wordIdx] ); |
109 | } | 109 | } |
110 | clickWord = -1; | 110 | clickWord = -1; |
111 | repaint(); | 111 | repaint(); |
112 | } | 112 | } |
113 | 113 | ||