1 /*
2 
3 Copyright (c) 2006-2013 uim Project https://github.com/uim/uim
4 
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31 
32 */
33 
34 #include "qtextutil.h"
35 
36 #include <cstdlib>
37 
38 #include <QtGui/QClipboard>
39 #if QT_VERSION < 0x050000
40 # include <QtGui/QApplication>
41 # include <QtGui/QLineEdit>
42 # include <QtGui/QTextEdit>
43 # ifdef ENABLE_QT4_QT3SUPPORT
44 #  include <Qt3Support/Q3TextEdit>
45 # endif
46 #else
47 # include <QtWidgets/QApplication>
48 # include <QtWidgets/QLineEdit>
49 # include <QtWidgets/QTextEdit>
50 #endif
51 
52 #if QT_VERSION < 0x050000
53 # include "quiminputcontext.h"
54 #else
55 # include <quimplatforminputcontext.h>
56 #endif
57 
QUimTextUtil(QObject * parent)58 QUimTextUtil::QUimTextUtil( QObject *parent )
59         : QObject( parent )
60 {
61 #if QT_VERSION < 0x050000
62     mIc = static_cast<QUimInputContext *>( parent );
63 #else
64     mIc = static_cast<QUimPlatformInputContext *>( parent );
65 #endif
66     mPreeditSaved = false;
67 }
68 
~QUimTextUtil()69 QUimTextUtil::~QUimTextUtil()
70 {
71 }
72 
73 int
acquire_text_cb(void * ptr,enum UTextArea text_id,enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)74 QUimTextUtil::acquire_text_cb( void *ptr, enum UTextArea text_id,
75                                enum UTextOrigin origin,
76                                int former_req_len, int latter_req_len,
77                                char **former, char **latter )
78 {
79     int err;
80 #if QT_VERSION < 0x050000
81     QUimInputContext *ic = static_cast<QUimInputContext *>( ptr );
82 #else
83     QUimPlatformInputContext *ic
84         = static_cast<QUimPlatformInputContext *>( ptr );
85 #endif
86     QUimTextUtil *tu = ic->textUtil();
87 
88     switch ( text_id ) {
89     case UTextArea_Primary:
90         err = tu->acquirePrimaryText( origin, former_req_len, latter_req_len,
91                                       former, latter );
92         break;
93     case UTextArea_Selection:
94         err = tu->acquireSelectionText( origin, former_req_len, latter_req_len,
95                                         former, latter );
96         break;
97     case UTextArea_Clipboard:
98         err = tu->acquireClipboardText( origin, former_req_len, latter_req_len,
99                                         former, latter );
100         break;
101     case UTextArea_Unspecified:
102     default:
103         err = -1;
104     }
105 
106     return err;
107 }
108 
109 int
delete_text_cb(void * ptr,enum UTextArea text_id,enum UTextOrigin origin,int former_req_len,int latter_req_len)110 QUimTextUtil::delete_text_cb( void *ptr, enum UTextArea text_id,
111                               enum UTextOrigin origin,
112                               int former_req_len, int latter_req_len )
113 {
114     int err;
115 #if QT_VERSION < 0x050000
116     QUimInputContext *ic = static_cast<QUimInputContext *>( ptr );
117 #else
118     QUimPlatformInputContext *ic
119         = static_cast<QUimPlatformInputContext *>( ptr );
120 #endif
121     QUimTextUtil *tu = ic->textUtil();
122 
123     switch ( text_id ) {
124     case UTextArea_Primary:
125         err = tu->deletePrimaryText( origin, former_req_len, latter_req_len );
126         break;
127     case UTextArea_Selection:
128         err = tu->deleteSelectionText( origin, former_req_len, latter_req_len );
129         break;
130     case UTextArea_Clipboard:
131     case UTextArea_Unspecified:
132     default:
133         err = -1;
134         break;
135     }
136 
137     return err;
138 }
139 
140 int
acquirePrimaryText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)141 QUimTextUtil::acquirePrimaryText( enum UTextOrigin origin,
142                                   int former_req_len, int latter_req_len,
143                                   char **former, char **latter )
144 {
145     int err;
146 #if defined(Q_WS_X11) || defined(Q_OS_UNIX)
147     mWidget = QApplication::focusWidget();
148 #else
149     return -1;
150 #endif
151 
152     if ( qobject_cast<QLineEdit *>( mWidget ) )
153         err = acquirePrimaryTextInQLineEdit( origin, former_req_len,
154                                              latter_req_len, former, latter );
155     else if ( qobject_cast<QTextEdit *>( mWidget ) )
156         err = acquirePrimaryTextInQTextEdit( origin, former_req_len,
157                                              latter_req_len, former, latter );
158 #ifdef ENABLE_QT4_QT3SUPPORT
159     else if ( qobject_cast<Q3TextEdit *>( mWidget ) )
160         err = acquirePrimaryTextInQ3TextEdit( origin, former_req_len,
161                                               latter_req_len, former, latter );
162 #endif
163     else
164         // FIXME other widgets?
165         err = -1;
166 
167     return err;
168 }
169 
170 int
acquirePrimaryTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)171 QUimTextUtil::acquirePrimaryTextInQLineEdit( enum UTextOrigin origin,
172                                              int former_req_len,
173                                              int latter_req_len,
174                                              char **former, char **latter )
175 {
176     QLineEdit *edit = static_cast<QLineEdit *>( mWidget );
177     QString text, former_text, latter_text;
178     int cursor_index, len, precedence_len, following_len, offset;
179     int preedit_len, preedit_cursor_pos;
180 
181     preedit_len = mIc->getPreeditString().length();
182     preedit_cursor_pos = mIc->getPreeditCursorPosition();
183 
184     text = edit->text(); // excluding preedit string
185     len = text.length();
186     cursor_index = edit->cursorPosition() + preedit_len;
187 
188     precedence_len = cursor_index - preedit_cursor_pos;
189     following_len = len - precedence_len;
190 
191     switch ( origin ) {
192     case UTextOrigin_Cursor:
193         offset = 0;
194         if ( former_req_len >= 0 ) {
195             if ( precedence_len > former_req_len )
196               offset = precedence_len - former_req_len;
197         } else {
198             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
199                 return -1;
200         }
201         *former = strdup(
202             text.mid( offset, precedence_len - offset ).toUtf8().data() );
203 
204         offset = 0;
205         if ( latter_req_len >= 0 ) {
206             if ( following_len > latter_req_len )
207                 offset = following_len - latter_req_len;
208         } else {
209             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
210                 free( *former );
211                 return -1;
212             }
213         }
214         *latter = strdup( text.mid( precedence_len + preedit_len,
215             following_len - offset ).toUtf8().data() );
216         break;
217 
218     case UTextOrigin_Beginning:
219         *former = 0;
220         if ( latter_req_len >= 0 ) {
221             if ( precedence_len >= latter_req_len )
222                 text = text.left( latter_req_len );
223             else {
224                 former_text = text.left( precedence_len );
225                 if ( following_len >= ( latter_req_len - precedence_len ) )
226                     latter_text = text.mid( precedence_len + preedit_len, ( latter_req_len - precedence_len ) );
227                 else
228                     latter_text = text.mid( precedence_len + preedit_len, following_len );
229                 text = former_text + latter_text;
230             }
231         } else {
232             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
233                 return -1;
234 
235             former_text = text.left( precedence_len );
236             latter_text = text.mid( precedence_len + preedit_len, following_len );
237             text = former_text + latter_text;
238         }
239         *latter = strdup( text.toUtf8().data() );
240         break;
241 
242     case UTextOrigin_End:
243         if ( former_req_len >= 0 ) {
244             if ( following_len >= former_req_len )
245                 text = text.right( former_req_len );
246             else {
247                     latter_text = text.right( following_len );
248                 if ( precedence_len >= ( former_req_len - following_len ) )
249                     former_text = text.mid( precedence_len - ( former_req_len - following_len ), former_req_len - following_len );
250                 else
251                     former_text = text.left( precedence_len );
252                 text = former_text + latter_text;
253             }
254         } else {
255             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
256                 return -1;
257 
258             former_text = text.left( precedence_len );
259             latter_text = text.right( following_len );
260             text = former_text + latter_text;
261         }
262         *former = strdup( text.toUtf8().data() );
263         *latter = 0;
264         break;
265 
266     case UTextOrigin_Unspecified:
267     default:
268         return -1;
269     }
270 
271     return 0;
272 }
273 
274 int
acquirePrimaryTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)275 QUimTextUtil::acquirePrimaryTextInQTextEdit( enum UTextOrigin origin,
276                                              int former_req_len,
277                                              int latter_req_len,
278                                              char **former, char **latter )
279 {
280     QTextEdit *edit = static_cast<QTextEdit *>( mWidget );
281     QString text = edit->toPlainText(); // excluding preedit string
282     int len = text.length();
283 
284     int preedit_len = mIc->getPreeditString().length();
285     int preedit_cursor_pos = mIc->getPreeditCursorPosition();
286 
287     int cursor_index = edit->textCursor().position() + preedit_len;
288     int precedence_len = cursor_index - preedit_cursor_pos;
289     int following_len = len - precedence_len;
290 
291     QString former_text;
292     QString latter_text;
293     switch ( origin ) {
294     case UTextOrigin_Cursor:
295         {
296             int offset = 0;
297             if ( former_req_len >= 0 ) {
298                 if ( precedence_len > former_req_len )
299                   offset = precedence_len - former_req_len;
300             } else {
301                 if (! ( ~former_req_len
302                         & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
303                     return -1;
304             }
305             *former = strdup(
306                 text.mid( offset, precedence_len - offset ).toUtf8().data() );
307 
308             offset = 0;
309             if ( latter_req_len >= 0 ) {
310                 if ( following_len > latter_req_len )
311                     offset = following_len - latter_req_len;
312             } else {
313                 if (! ( ~latter_req_len
314                         & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
315                     free( *former );
316                     return -1;
317                 }
318             }
319             *latter = strdup( text.mid( precedence_len + preedit_len,
320                 following_len - offset ).toUtf8().data() );
321             break;
322         }
323 
324     case UTextOrigin_Beginning:
325         *former = 0;
326         if ( latter_req_len >= 0 ) {
327             if ( precedence_len >= latter_req_len )
328                 text = text.left( latter_req_len );
329             else {
330                 former_text = text.left( precedence_len );
331                 if ( following_len >= ( latter_req_len - precedence_len ) )
332                     latter_text = text.mid( precedence_len + preedit_len,
333                             ( latter_req_len - precedence_len ) );
334                 else
335                     latter_text = text.mid( precedence_len + preedit_len,
336                             following_len );
337                 text = former_text + latter_text;
338             }
339         } else {
340             if (! ( ~latter_req_len
341                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
342                 return -1;
343 
344             former_text = text.left( precedence_len );
345             latter_text = text.mid( precedence_len + preedit_len,
346                     following_len );
347             text = former_text + latter_text;
348         }
349         *latter = strdup( text.toUtf8().data() );
350         break;
351 
352     case UTextOrigin_End:
353         if ( former_req_len >= 0 ) {
354             if ( following_len >= former_req_len )
355                 text = text.right( former_req_len );
356             else {
357                     latter_text = text.right( following_len );
358                 if ( precedence_len >= ( former_req_len - following_len ) )
359                     former_text = text.mid( precedence_len
360                             - ( former_req_len - following_len ),
361                             former_req_len - following_len );
362                 else
363                     former_text = text.left( precedence_len );
364                 text = former_text + latter_text;
365             }
366         } else {
367             if (! ( ~former_req_len
368                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
369                 return -1;
370 
371             former_text = text.left( precedence_len );
372             latter_text = text.right( following_len );
373             text = former_text + latter_text;
374         }
375         *former = strdup( text.toUtf8().data() );
376         *latter = 0;
377         break;
378 
379     case UTextOrigin_Unspecified:
380     default:
381         return -1;
382     }
383 
384     return 0;
385 }
386 
387 #ifdef ENABLE_QT4_QT3SUPPORT
388 int
acquirePrimaryTextInQ3TextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)389 QUimTextUtil::acquirePrimaryTextInQ3TextEdit( enum UTextOrigin origin,
390                                               int former_req_len,
391                                               int latter_req_len,
392                                               char **former, char **latter )
393 {
394     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
395     QString text;
396 
397     int start_para, start_index, end_para, end_index, para, index;
398     int n_para;
399     int preedit_len, preedit_cursor_pos;
400     int sel_start_para, sel_start_index, sel_end_para, sel_end_index;
401     Qt::TextFormat format;
402 
403     format = edit->textFormat();
404     edit->setTextFormat( Qt::PlainText );
405 
406     edit->getCursorPosition( &para, &index ); // including preedit string
407 
408     // keep current selection
409     edit->getSelection( &sel_start_para, &sel_start_index, &sel_end_para,
410                         &sel_end_index, 0 );
411 
412     preedit_len = mIc->getPreeditString().length();
413     preedit_cursor_pos = mIc->getPreeditCursorPosition();
414     n_para = edit->paragraphs();
415 
416     switch ( origin ) {
417     case UTextOrigin_Cursor:
418         start_index = index - preedit_cursor_pos;
419         start_para = para;
420         end_index = start_index + preedit_len;
421         end_para = para;
422 
423         if ( former_req_len >= 0 ) {
424             for ( int i = 0; i < former_req_len; i++ )
425                 Q3TextEditPositionBackward( &start_para, &start_index );
426         } else {
427             if ( former_req_len == UTextExtent_Line )
428                 start_index = 0;
429             else if ( former_req_len == UTextExtent_Full ) {
430                 start_para = 0;
431                 start_index = 0;
432             } else {
433                 edit->setTextFormat( format );
434                 return -1;
435             }
436         }
437         edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
438         *former = strdup( edit->selectedText().toUtf8().data() );
439 
440         if ( latter_req_len >= 0 ) {
441             for ( int i = 0; i < latter_req_len; i++ )
442                 Q3TextEditPositionForward( &end_para, &end_index );
443         } else {
444             if ( latter_req_len == UTextExtent_Line ) {
445                 end_index = edit->paragraphLength( end_para );
446             } else if ( latter_req_len == UTextExtent_Full ) {
447                 end_para = n_para - 1;
448                 end_index = edit->paragraphLength( end_para );
449             } else {
450                 edit->setTextFormat( format );
451                 return -1;
452             }
453         }
454         edit->setSelection( para, index - preedit_cursor_pos + preedit_len,
455                             end_para, end_index, 0 );
456         *latter = strdup( edit->selectedText().toUtf8().data() );
457         break;
458 
459     case UTextOrigin_Beginning:
460         *former = 0;
461 
462         start_para = 0;
463         start_index = 0;
464         end_para = start_para;
465         end_index = start_index;
466 
467         if ( latter_req_len >= 0 ) {
468             for ( int i = 0; i < latter_req_len; i++ )
469                 Q3TextEditPositionForward( &end_para, &end_index );
470         } else {
471             if ( latter_req_len == UTextExtent_Line )
472                 end_index = edit->paragraphLength( end_para );
473             else if ( latter_req_len == UTextExtent_Full ) {
474                 end_para = n_para - 1;
475                 end_index = edit->paragraphLength( end_para );
476             } else {
477                 edit->setTextFormat( format );
478                 return -1;
479             }
480         }
481         if ( end_para < para || ( end_para == para && end_index <= ( index - preedit_cursor_pos ) ) ) {
482             edit->setSelection( start_para, start_index, end_para, end_index, 0 );
483             text = edit->selectedText();
484         } else {
485             edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
486             text = edit->selectedText();
487             edit->setSelection( para, index - preedit_cursor_pos + preedit_len, end_para, end_index, 0 );
488             text += edit->selectedText();
489         }
490         *latter = strdup( text.toUtf8().data() );
491         break;
492 
493     case UTextOrigin_End:
494 
495         end_para = n_para - 1;
496         end_index = edit->paragraphLength( end_para );
497         start_para = end_para;
498         start_index = end_index;
499 
500         if ( former_req_len >= 0 ) {
501             for ( int i = 0; i < former_req_len; i++ )
502                 Q3TextEditPositionBackward( &start_para, &start_index );
503         } else {
504             if ( former_req_len == UTextExtent_Line )
505                 start_index = 0;
506             else if ( former_req_len == UTextExtent_Full ) {
507                 start_para = 0;
508                 start_index = 0;
509             } else {
510                 edit->setTextFormat( format );
511                 return -1;
512             }
513         }
514         if ( start_para > para || ( start_para == para && start_index >= ( index - preedit_cursor_pos + preedit_len ) ) ) {
515             edit->setSelection( start_para, start_index, end_para, end_index, 0 );
516             text = edit->selectedText();
517         } else {
518 
519             edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
520             text = edit->selectedText();
521 
522             edit->setSelection( para, index - preedit_cursor_pos + preedit_len, end_para, end_index, 0 );
523             text += edit->selectedText();
524         }
525         *former = strdup( text.toUtf8().data() );
526         *latter = 0;
527         break;
528 
529     case UTextOrigin_Unspecified:
530     default:
531         edit->setTextFormat( format );
532         return -1;
533     }
534 
535     if ( sel_start_para != -1 && sel_start_index != -1 && sel_end_para != -1 &&
536          sel_end_index != -1 )
537         edit->setSelection( sel_start_index, sel_start_index, sel_end_para, sel_end_index, 0 );
538     else
539         edit->removeSelection( 0 );
540 
541     edit->setCursorPosition( para, index );
542 
543     edit->setTextFormat( format );
544     return 0;
545 }
546 #endif
547 
548 int
acquireSelectionText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)549 QUimTextUtil::acquireSelectionText( enum UTextOrigin origin,
550                                     int former_req_len, int latter_req_len,
551                                     char **former, char **latter )
552 {
553     int err;
554 #if defined(Q_WS_X11) || defined(Q_OS_UNIX)
555     mWidget = QApplication::focusWidget();
556 #else
557     return -1;
558 #endif
559 
560     if ( qobject_cast<QLineEdit *>( mWidget ) )
561         err = acquireSelectionTextInQLineEdit( origin, former_req_len,
562                                                latter_req_len, former, latter );
563     else if ( qobject_cast<QTextEdit *>( mWidget ) )
564         err = acquireSelectionTextInQTextEdit( origin, former_req_len,
565                                                latter_req_len, former, latter );
566 #ifdef ENABLE_QT4_QT3SUPPORT
567     else if ( qobject_cast<Q3TextEdit *>( mWidget ) )
568         err = acquireSelectionTextInQ3TextEdit( origin, former_req_len,
569                                                 latter_req_len, former,
570                                                 latter );
571 #endif
572     else
573         // FIXME other widgets?
574         err = -1;
575 
576     return err;
577 }
578 
579 int
acquireSelectionTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)580 QUimTextUtil::acquireSelectionTextInQLineEdit( enum UTextOrigin origin,
581                                                int former_req_len,
582                                                int latter_req_len,
583                                                char **former, char **latter )
584 {
585     QLineEdit *edit = static_cast<QLineEdit *>( mWidget );
586     QString text;
587     int len, offset, start, current;
588     bool cursor_at_beginning = false;
589 
590     if ( ! edit->hasSelectedText() )
591         return -1;
592 
593     current = edit->cursorPosition();
594     start = edit->selectionStart();
595 
596     if ( current == start )
597         cursor_at_beginning = true;
598 
599     text = edit->selectedText();
600     len = text.length();
601 
602     if ( origin == UTextOrigin_Beginning ||
603          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
604         *former = 0;
605         offset = 0;
606         if ( latter_req_len >= 0 ) {
607             if ( len > latter_req_len )
608                 offset = len - latter_req_len;
609         } else {
610             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
611                 return -1;
612         }
613         *latter = strdup( text.left( len - offset ).toUtf8().data() );
614     } else if ( origin == UTextOrigin_End ||
615                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
616         offset = 0;
617         if ( former_req_len >= 0 ) {
618             if ( len > former_req_len )
619                 offset = len - former_req_len;
620         } else {
621             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
622                 return -1;
623         }
624         *former = strdup( text.mid( offset, len - offset ).toUtf8().data() );
625         *latter = 0;
626     } else {
627         return -1;
628     }
629 
630     return 0;
631 }
632 
633 int
acquireSelectionTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)634 QUimTextUtil::acquireSelectionTextInQTextEdit( enum UTextOrigin origin,
635                                                int former_req_len,
636                                                int latter_req_len,
637                                                char **former, char **latter )
638 {
639     QTextEdit *edit = static_cast<QTextEdit *>( mWidget );
640     QTextCursor cursor = edit->textCursor();
641     if ( ! cursor.hasSelection() )
642         return -1;
643 
644     bool cursor_at_beginning = false;
645     int current = cursor.position();
646     int start = cursor.selectionStart();
647     if ( current == start )
648         cursor_at_beginning = true;
649 
650     QString text = cursor.selectedText();
651     int len = text.length();
652     int offset;
653     if ( origin == UTextOrigin_Beginning ||
654          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
655         *former = 0;
656         offset = 0;
657         if ( latter_req_len >= 0 ) {
658             if ( len > latter_req_len )
659                 offset = len - latter_req_len;
660         } else {
661             if (! ( ~latter_req_len
662                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
663                 return -1;
664         }
665         *latter = strdup( text.left( len - offset ).toUtf8().data() );
666     } else if ( origin == UTextOrigin_End ||
667                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
668         offset = 0;
669         if ( former_req_len >= 0 ) {
670             if ( len > former_req_len )
671                 offset = len - former_req_len;
672         } else {
673             if (! ( ~former_req_len
674                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
675                 return -1;
676         }
677         *former = strdup( text.mid( offset, len - offset ).toUtf8().data() );
678         *latter = 0;
679     } else {
680         return -1;
681     }
682 
683     return 0;
684 }
685 
686 #ifdef ENABLE_QT4_QT3SUPPORT
687 int
acquireSelectionTextInQ3TextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)688 QUimTextUtil::acquireSelectionTextInQ3TextEdit( enum UTextOrigin origin,
689                                                 int former_req_len,
690                                                 int latter_req_len,
691                                                 char **former, char **latter )
692 {
693     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
694     QString text;
695     int len, offset, newline;
696     int start_para, start_index, end_para, end_index;
697     int para, index;
698     bool cursor_at_beginning = false;
699     Qt::TextFormat format;
700 
701     if ( ! edit->hasSelectedText() )
702         return -1;
703 
704     format = edit->textFormat();
705     edit->setTextFormat( Qt::PlainText );
706 
707     edit->getCursorPosition( &para, &index );
708     edit->getSelection(&start_para, &start_index, &end_para, &end_index, 0 );
709 
710     if ( para == start_para && index == start_index )
711         cursor_at_beginning = true;
712 
713     text = edit->selectedText();
714     len = text.length();
715 
716     if ( origin == UTextOrigin_Beginning ||
717          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
718         *former = 0;
719         offset = 0;
720         if ( latter_req_len >= 0 ) {
721             if ( len > latter_req_len )
722                 offset = len - latter_req_len;
723         } else {
724             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
725                 edit->setTextFormat( format );
726                 return -1;
727             }
728 
729             if ( latter_req_len == UTextExtent_Line && ( ( newline = text.indexOf( '\n' ) ) != -1 ) )
730                 offset = len - newline;
731         }
732         *latter = strdup( text.left( len - offset ).toUtf8().data() );
733     } else if ( origin == UTextOrigin_End ||
734                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
735         offset = 0;
736         if ( former_req_len >= 0 ) {
737             if ( len > former_req_len )
738                 offset = len - former_req_len;
739         } else {
740             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
741                 edit->setTextFormat( format );
742                 return -1;
743             }
744 
745             if ( former_req_len == UTextExtent_Line && ( ( newline = text.lastIndexOf( '\n' ) ) != -1 ) )
746                 offset = newline + 1;
747         }
748         *former = strdup( text.mid( offset, len - offset ).toUtf8().data() );
749         *latter = 0;
750     } else {
751         edit->setTextFormat( format );
752         return -1;
753     }
754 
755     edit->setTextFormat( format );
756     return 0;
757 }
758 #endif
759 
760 int
acquireClipboardText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)761 QUimTextUtil::acquireClipboardText( enum UTextOrigin origin,
762                                     int former_req_len, int latter_req_len,
763                                     char **former, char **latter )
764 {
765     QClipboard *cb = QApplication::clipboard();
766     QString text = cb->text( QClipboard::Clipboard );
767     int len, offset, newline;
768 
769     if ( text.isNull() )
770         return -1;
771 
772     len = text.length();
773 
774     /* Cursor position is assumed to be at the end */
775     switch ( origin ) {
776     case UTextOrigin_Cursor:
777     case UTextOrigin_End:
778         offset = 0;
779         if ( former_req_len >= 0 ) {
780             if ( former_req_len < len )
781                 offset = len - former_req_len;
782         } else {
783             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
784                 return -1;
785 
786             if ( former_req_len == UTextExtent_Line
787                 && ( ( newline = text.lastIndexOf( '\n' ) ) != -1 ) )
788                 offset = newline + 1;
789         }
790         *former = strdup( text.mid( offset, len - offset ).toUtf8().data() );
791         *latter = 0;
792         break;
793 
794     case UTextOrigin_Beginning:
795         *former = 0;
796         offset = 0;
797         if ( latter_req_len >= 0 ) {
798             if ( latter_req_len < len )
799                 offset = len - latter_req_len;
800         } else {
801             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
802                 return -1;
803 
804             if ( latter_req_len == UTextExtent_Line
805                 && ( ( newline = text.indexOf( '\n' ) ) != -1 ) )
806                 offset = len - newline;
807         }
808         *latter = strdup( text.left( len - offset ).toUtf8().data() );
809         break;
810 
811     case UTextOrigin_Unspecified:
812     default:
813         return -1;
814     }
815 
816     return 0;
817 }
818 
819 int
deletePrimaryText(enum UTextOrigin origin,int former_req_len,int latter_req_len)820 QUimTextUtil::deletePrimaryText( enum UTextOrigin origin, int former_req_len,
821                                  int latter_req_len )
822 {
823     int err;
824 #if defined(Q_WS_X11) || defined(Q_OS_UNIX)
825     mWidget = QApplication::focusWidget();
826 #else
827     return -1;
828 #endif
829 
830     if ( qobject_cast<QLineEdit *>( mWidget ) )
831         err = deletePrimaryTextInQLineEdit( origin, former_req_len,
832                                             latter_req_len );
833     else if ( qobject_cast<QTextEdit *>( mWidget ) )
834         err = deletePrimaryTextInQTextEdit( origin, former_req_len,
835                                              latter_req_len );
836 #ifdef ENABLE_QT4_QT3SUPPORT
837     else if ( qobject_cast<Q3TextEdit *>( mWidget ) )
838         err = deletePrimaryTextInQ3TextEdit( origin, former_req_len,
839                                              latter_req_len );
840 #endif
841     else
842         // FIXME other widgets?
843         err = -1;
844 
845     return err;
846 }
847 
848 int
deletePrimaryTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)849 QUimTextUtil::deletePrimaryTextInQLineEdit( enum UTextOrigin origin,
850                                             int former_req_len,
851                                             int latter_req_len )
852 {
853     QLineEdit *edit = static_cast<QLineEdit *>( mWidget );
854     QString text;
855     int len, precedence_len, following_len;
856     int preedit_len;
857     int former_del_start;
858     int latter_del_end;
859 
860     preedit_len = mIc->getPreeditString().length();
861 
862     text = edit->text(); // excluding preedit string
863     len = text.length();
864     precedence_len = edit->cursorPosition();
865     following_len = len - precedence_len;
866 
867     switch ( origin ) {
868     case UTextOrigin_Cursor:
869         former_del_start = 0;
870         if ( former_req_len >= 0 ) {
871             if ( precedence_len > former_req_len )
872                 former_del_start = precedence_len - former_req_len;
873         } else {
874             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
875                 return -1;
876         }
877         latter_del_end = len + preedit_len;
878         if ( latter_req_len >= 0 ) {
879             if ( following_len > latter_req_len )
880                 latter_del_end = precedence_len + preedit_len + latter_req_len;
881         } else {
882             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
883                 return -1;
884         }
885         break;
886 
887     case UTextOrigin_Beginning:
888         former_del_start = 0;
889         latter_del_end = precedence_len + preedit_len;
890         if ( latter_req_len >= 0 ) {
891             if ( precedence_len < latter_req_len ) {
892                 if ( following_len >= ( latter_req_len - precedence_len ) )
893                     latter_del_end = preedit_len + latter_req_len;
894                 else
895                     latter_del_end = len + preedit_len;
896             }
897         } else {
898             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
899                 return -1;
900             latter_del_end = len + preedit_len;
901         }
902         break;
903 
904     case UTextOrigin_End:
905         former_del_start = precedence_len;
906         latter_del_end = len + preedit_len;
907         if ( former_req_len < 0 ) {
908             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
909                 return -1;
910 
911             former_del_start = 0;
912         }
913         break;
914 
915     case UTextOrigin_Unspecified:
916     default:
917         return -1;
918     }
919 
920     edit->setText( text.left( former_del_start ) + text.right( len - latter_del_end + preedit_len ) );
921     edit->setCursorPosition( former_del_start );
922 
923     return 0;
924 }
925 
926 int
deletePrimaryTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)927 QUimTextUtil::deletePrimaryTextInQTextEdit( enum UTextOrigin origin,
928                                             int former_req_len,
929                                             int latter_req_len )
930 {
931     QTextEdit *edit = static_cast<QTextEdit *>( mWidget );
932     QString text = edit->toPlainText(); // excluding preedit string
933     int len = text.length();
934 
935     int preedit_len = mIc->getPreeditString().length();
936 
937     QTextCursor cursor = edit->textCursor();
938     int precedence_len = cursor.position();
939     int following_len = len - precedence_len;
940 
941     int former_del_start;
942     int latter_del_end;
943     switch ( origin ) {
944     case UTextOrigin_Cursor:
945         former_del_start = 0;
946         if ( former_req_len >= 0 ) {
947             if ( precedence_len > former_req_len )
948                 former_del_start = precedence_len - former_req_len;
949         } else {
950             if (! ( ~former_req_len
951                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
952                 return -1;
953         }
954         latter_del_end = len + preedit_len;
955         if ( latter_req_len >= 0 ) {
956             if ( following_len > latter_req_len )
957                 latter_del_end = precedence_len + preedit_len + latter_req_len;
958         } else {
959             if (! ( ~latter_req_len
960                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
961                 return -1;
962         }
963         break;
964 
965     case UTextOrigin_Beginning:
966         former_del_start = 0;
967         latter_del_end = precedence_len + preedit_len;
968         if ( latter_req_len >= 0 ) {
969             if ( precedence_len < latter_req_len ) {
970                 if ( following_len >= ( latter_req_len - precedence_len ) )
971                     latter_del_end = preedit_len + latter_req_len;
972                 else
973                     latter_del_end = len + preedit_len;
974             }
975         } else {
976             if (! ( ~latter_req_len
977                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
978                 return -1;
979             latter_del_end = len + preedit_len;
980         }
981         break;
982 
983     case UTextOrigin_End:
984         former_del_start = precedence_len;
985         latter_del_end = len + preedit_len;
986         if ( former_req_len < 0 ) {
987             if (! ( ~former_req_len
988                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
989                 return -1;
990 
991             former_del_start = 0;
992         }
993         break;
994 
995     case UTextOrigin_Unspecified:
996     default:
997         return -1;
998     }
999 
1000     // don't call setText() to avoid flicker unlike QLineEdit
1001     int end_index = latter_del_end - preedit_len;
1002     if ( precedence_len != end_index ) {
1003         cursor.setPosition( precedence_len );
1004         cursor.setPosition( end_index, QTextCursor::KeepAnchor );
1005         edit->setTextCursor( cursor );
1006         cursor.deleteChar();
1007     }
1008     if ( precedence_len != former_del_start ) {
1009         cursor.setPosition( precedence_len );
1010         cursor.setPosition( former_del_start, QTextCursor::KeepAnchor );
1011         edit->setTextCursor( cursor );
1012         cursor.deleteChar();
1013     }
1014 
1015     return 0;
1016 }
1017 
1018 #ifdef ENABLE_QT4_QT3SUPPORT
1019 int
deletePrimaryTextInQ3TextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)1020 QUimTextUtil::deletePrimaryTextInQ3TextEdit( enum UTextOrigin origin,
1021                                              int former_req_len,
1022                                              int latter_req_len )
1023 {
1024     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
1025     int start_para, start_index, end_para, end_index, para, index;
1026     int n_para;
1027 
1028     savePreedit();
1029 
1030     edit->getCursorPosition( &para, &index );
1031     n_para = edit->paragraphs();
1032 
1033     switch ( origin ) {
1034     case UTextOrigin_Cursor:
1035         start_index = index;
1036         start_para = para;
1037         end_index = start_index;
1038         end_para = para;
1039 
1040         if ( former_req_len >= 0 ) {
1041             for ( int i = 0; i < former_req_len; i++ )
1042                 Q3TextEditPositionBackward( &start_para, &start_index );
1043         } else {
1044             if ( former_req_len == UTextExtent_Line ) {
1045                 start_index = 0;
1046             } else if ( former_req_len == UTextExtent_Full ) {
1047                 start_para = 0;
1048                 start_index = 0;
1049             } else {
1050                 restorePreedit();
1051                 return -1;
1052             }
1053         }
1054         if ( latter_req_len >= 0 ) {
1055             for ( int i = 0; i < latter_req_len; i++ )
1056                 Q3TextEditPositionForward( &end_para, &end_index );
1057         } else {
1058             if ( latter_req_len == UTextExtent_Line ) {
1059                 end_index = edit->paragraphLength( end_para );
1060             } else if ( latter_req_len == UTextExtent_Full ) {
1061                 end_para = n_para - 1;
1062                 end_index = edit->paragraphLength( end_para );
1063             } else {
1064                 restorePreedit();
1065                 return -1;
1066             }
1067         }
1068         break;
1069 
1070     case UTextOrigin_Beginning:
1071         start_para = 0;
1072         start_index = 0;
1073         end_para = start_para;
1074         end_index = start_index;
1075 
1076         if ( latter_req_len >= 0 ) {
1077             for ( int i = 0; i < latter_req_len; i++ )
1078                 Q3TextEditPositionForward( &end_para, &end_index );
1079         } else {
1080             if ( latter_req_len == UTextExtent_Line ) {
1081                 end_index = edit->paragraphLength( end_para );
1082             } else if ( latter_req_len == UTextExtent_Full ) {
1083                 end_para = n_para - 1;
1084                 end_index = edit->paragraphLength( end_para );
1085             } else {
1086                 restorePreedit();
1087                 return -1;
1088             }
1089         }
1090         break;
1091 
1092     case UTextOrigin_End:
1093         end_para = n_para - 1;
1094         end_index = edit->paragraphLength( end_para );
1095         start_para = end_para;
1096         start_index = end_index;
1097 
1098         if ( former_req_len >= 0 ) {
1099             for ( int i = 0; i < former_req_len; i++ )
1100                 Q3TextEditPositionBackward( &start_para, &start_index );
1101         } else {
1102             if ( former_req_len == UTextExtent_Line )
1103                 start_index = 0;
1104             else if ( former_req_len == UTextExtent_Full ) {
1105                 start_para = 0;
1106                 start_index = 0;
1107             } else {
1108                 restorePreedit();
1109                 return -1;
1110             }
1111         }
1112         break;
1113 
1114     case UTextOrigin_Unspecified:
1115     default:
1116         restorePreedit();
1117         return -1;
1118     }
1119     edit->setSelection( start_para, start_index, end_para, end_index, 1 );
1120     edit->removeSelectedText( 1 );
1121     edit->setCursorPosition( start_para, start_index );
1122     restorePreedit();
1123 
1124     return 0;
1125 }
1126 #endif
1127 
1128 int
deleteSelectionText(enum UTextOrigin origin,int former_req_len,int latter_req_len)1129 QUimTextUtil::deleteSelectionText( enum UTextOrigin origin,
1130                                    int former_req_len, int latter_req_len )
1131 {
1132     int err;
1133 #if defined(Q_WS_X11) || defined(Q_OS_UNIX)
1134     mWidget = QApplication::focusWidget();
1135 #else
1136     return -1;
1137 #endif
1138 
1139     if ( qobject_cast<QLineEdit *>( mWidget ) )
1140         err = deleteSelectionTextInQLineEdit( origin, former_req_len,
1141                                               latter_req_len );
1142     else if ( qobject_cast<QTextEdit *>( mWidget ) )
1143         err = deleteSelectionTextInQTextEdit( origin, former_req_len,
1144                                               latter_req_len );
1145 #ifdef ENABLE_QT4_QT3SUPPORT
1146     else if ( qobject_cast<Q3TextEdit *>( mWidget ) )
1147         err = deleteSelectionTextInQ3TextEdit( origin, former_req_len,
1148                                                latter_req_len );
1149 #endif
1150     else
1151         // FIXME other widgets?
1152         err = -1;
1153 
1154     return err;
1155 }
1156 
1157 int
deleteSelectionTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)1158 QUimTextUtil::deleteSelectionTextInQLineEdit( enum UTextOrigin origin,
1159                                               int former_req_len,
1160                                               int latter_req_len )
1161 {
1162     QLineEdit *edit = static_cast<QLineEdit *>( mWidget );
1163     QString text;
1164     int len, start, end, current;
1165     bool cursor_at_beginning = false;
1166 
1167     if ( ! edit->hasSelectedText() )
1168         return -1;
1169 
1170     current = edit->cursorPosition();
1171     start = edit->selectionStart();
1172     if ( current == start )
1173         cursor_at_beginning = true;
1174 
1175     text = edit->selectedText();
1176     len = text.length();
1177     end = start + len;
1178 
1179     if ( origin == UTextOrigin_Beginning ||
1180          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
1181         if ( latter_req_len >= 0 ) {
1182             if ( len > latter_req_len )
1183                 end = start + latter_req_len;
1184         } else {
1185             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1186                 return -1;
1187         }
1188     } else if ( origin == UTextOrigin_End ||
1189                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
1190         if ( former_req_len >= 0 ) {
1191             if ( len > former_req_len )
1192                 start = end - former_req_len;
1193         } else {
1194             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1195                 return -1;
1196         }
1197     } else {
1198         return -1;
1199     }
1200     edit->setSelection( start, end - start );
1201     edit->del();
1202 
1203     return 0;
1204 }
1205 
1206 int
deleteSelectionTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)1207 QUimTextUtil::deleteSelectionTextInQTextEdit( enum UTextOrigin origin,
1208                                               int former_req_len,
1209                                               int latter_req_len )
1210 {
1211     QTextEdit *edit = static_cast<QTextEdit *>( mWidget );
1212     QTextCursor cursor = edit->textCursor();
1213     if ( ! cursor.hasSelection() )
1214         return -1;
1215 
1216     bool cursor_at_beginning = false;
1217     int current = cursor.position();
1218     int start = cursor.selectionStart();
1219     if ( current == start )
1220         cursor_at_beginning = true;
1221 
1222     QString text = cursor.selectedText();
1223     int len = text.length();
1224     int end = start + len;
1225     if ( origin == UTextOrigin_Beginning ||
1226          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
1227         if ( latter_req_len >= 0 ) {
1228             if ( len > latter_req_len )
1229                 end = start + latter_req_len;
1230         } else {
1231             if (! ( ~latter_req_len
1232                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1233                 return -1;
1234         }
1235     } else if ( origin == UTextOrigin_End ||
1236                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
1237         if ( former_req_len >= 0 ) {
1238             if ( len > former_req_len )
1239                 start = end - former_req_len;
1240         } else {
1241             if (! ( ~former_req_len
1242                     & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1243                 return -1;
1244         }
1245     } else {
1246         return -1;
1247     }
1248     cursor.setPosition( start );
1249     cursor.setPosition( end, QTextCursor::KeepAnchor );
1250     edit->setTextCursor( cursor );
1251     cursor.deleteChar();
1252 
1253     return 0;
1254 }
1255 
1256 #ifdef ENABLE_QT4_QT3SUPPORT
1257 int
deleteSelectionTextInQ3TextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)1258 QUimTextUtil::deleteSelectionTextInQ3TextEdit( enum UTextOrigin origin,
1259                                                int former_req_len,
1260                                                int latter_req_len )
1261 {
1262     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
1263     QString text;
1264     int len, newline;
1265     int para, index;
1266     int sel_para_from, sel_index_from, sel_para_to, sel_index_to;
1267     int start_para, start_index, end_para, end_index;
1268     bool cursor_at_beginning = false;
1269 
1270     if ( ! edit->hasSelectedText() )
1271         return -1;
1272 
1273     edit->getCursorPosition( &para, &index );
1274     edit->getSelection( &sel_para_from, &sel_index_from, &sel_para_to, &sel_index_to, 0 );
1275 
1276     if ( para == sel_para_from && index == sel_index_from )
1277         cursor_at_beginning = true;
1278 
1279     text = edit->selectedText();
1280     len = text.length();
1281 
1282     start_para = sel_para_from;
1283     start_index = sel_index_from;
1284     end_para = sel_para_to;
1285     end_index = sel_index_to;
1286 
1287     if ( origin == UTextOrigin_Beginning ||
1288          ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
1289         edit->setCursorPosition( sel_para_from, sel_index_from );
1290         if ( latter_req_len >= 0 ) {
1291             if ( len > latter_req_len ) {
1292                 end_para = sel_para_from;
1293                 end_index = sel_index_from;
1294                 for ( int i = 0; i < latter_req_len; i++)
1295                     Q3TextEditPositionForward( &end_para, &end_index );
1296             }
1297         } else {
1298             if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1299                 return -1;
1300 
1301             if ( latter_req_len == UTextExtent_Line && ( ( newline = text.indexOf('\n') ) != -1 ) ) {
1302                 end_para = sel_para_from;
1303                 end_index = sel_index_from + newline;
1304             }
1305         }
1306     } else if ( origin == UTextOrigin_End ||
1307                 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
1308         if ( former_req_len >= 0 ) {
1309             if ( len > former_req_len ) {
1310                 start_para = sel_para_to;
1311                 start_index = sel_index_to;
1312                 for ( int i = 0; i < former_req_len; i++)
1313                     Q3TextEditPositionBackward( &start_para, &start_index );
1314             }
1315         } else {
1316             if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
1317                 return -1;
1318 
1319             if ( former_req_len == UTextExtent_Line && ( ( newline = text.lastIndexOf( '\n' ) ) != -1 ) ) {
1320                 start_para = sel_para_to;
1321                 start_index = 0;
1322             }
1323         }
1324     } else {
1325         return -1;
1326     }
1327     edit->setSelection( start_para, start_index, end_para, end_index, 1 );
1328     edit->removeSelectedText( 1 );
1329 
1330     return 0;
1331 }
1332 
1333 void
Q3TextEditPositionBackward(int * cursor_para,int * cursor_index)1334 QUimTextUtil::Q3TextEditPositionBackward( int *cursor_para, int *cursor_index )
1335 {
1336     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
1337     int preedit_len, preedit_cursor_pos;
1338     int para, index;
1339     int current_para, current_index;
1340 
1341     current_para = *cursor_para;
1342     current_index = *cursor_index;
1343 
1344     if ( ! mPreeditSaved ) {
1345         preedit_len = mIc->getPreeditString().length();
1346         preedit_cursor_pos = mIc->getPreeditCursorPosition();
1347     } else {
1348         preedit_len = 0;
1349         preedit_cursor_pos = 0;
1350     }
1351     edit->getCursorPosition( &para, &index );
1352 
1353     if ( current_para == para && current_index > ( index - preedit_cursor_pos ) && ( current_index <= ( index - preedit_cursor_pos + preedit_len ) ) )
1354         current_index = index - preedit_cursor_pos;
1355 
1356     if ( current_index > 0 )
1357         current_index--;
1358     else {
1359         if ( current_para > 0 ) {
1360             current_para--;
1361             current_index = edit->paragraphLength( current_para );
1362         }
1363     }
1364 
1365     *cursor_para = current_para;
1366     *cursor_index = current_index;
1367 }
1368 
1369 void
Q3TextEditPositionForward(int * cursor_para,int * cursor_index)1370 QUimTextUtil::Q3TextEditPositionForward( int *cursor_para, int *cursor_index )
1371 {
1372     Q3TextEdit *edit = static_cast<Q3TextEdit *>( mWidget );
1373     int n_para = edit->paragraphs();
1374     int preedit_len, preedit_cursor_pos;
1375     int current_para_len;
1376     int para, index;
1377     int current_para, current_index;
1378 
1379     current_para = *cursor_para;
1380     current_index = *cursor_index;
1381 
1382     current_para_len = edit->paragraphLength( current_para );
1383     if ( ! mPreeditSaved ) {
1384         preedit_len = mIc->getPreeditString().length();
1385         preedit_cursor_pos = mIc->getPreeditCursorPosition();
1386     } else {
1387         preedit_len = 0;
1388         preedit_cursor_pos = 0;
1389     }
1390     edit->getCursorPosition( &para, &index );
1391 
1392     if ( current_para == para && current_index >= ( index - preedit_cursor_pos ) && current_index < ( index - preedit_cursor_pos + preedit_len ) )
1393         current_index = index - preedit_cursor_pos + preedit_len;
1394 
1395     if ( current_para == n_para - 1 ) {
1396         if ( current_index < current_para_len )
1397             current_index++;
1398     } else {
1399         if ( current_index < current_para_len )
1400             current_index++;
1401         else {
1402             current_para++;
1403             current_index = 0;
1404         }
1405     }
1406 
1407     *cursor_para = current_para;
1408     *cursor_index = current_index;
1409 }
1410 #endif
1411 
savePreedit()1412 void QUimTextUtil::savePreedit()
1413 {
1414     mIc->saveContext();
1415     mPreeditSaved = true;
1416 }
1417 
restorePreedit()1418 void QUimTextUtil::restorePreedit()
1419 {
1420     mIc->restoreContext();
1421     mPreeditSaved = false;
1422 }
1423