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 #include <config.h>
34 #include <stdlib.h>
35
36 #include <qwidget.h>
37 #include <qlineedit.h>
38 #include <qtextedit.h>
39 #include <qapplication.h>
40 #include <qclipboard.h>
41
42 #include "uim/uim.h"
43
44 #include "qtextutil.h"
45 #include "quiminputcontext.h"
46
47
QUimTextUtil(QObject * parent)48 QUimTextUtil::QUimTextUtil( QObject *parent )
49 : QObject( parent )
50 {
51 mIc = (QUimInputContext *)parent;
52 mPreeditSaved = false;
53 }
54
~QUimTextUtil()55 QUimTextUtil::~QUimTextUtil()
56 {
57 }
58
59 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)60 QUimTextUtil::acquire_text_cb( void *ptr, enum UTextArea text_id,
61 enum UTextOrigin origin,
62 int former_req_len, int latter_req_len,
63 char **former, char **latter )
64 {
65 int err;
66 QUimInputContext *ic = (QUimInputContext *)ptr;
67 QUimTextUtil *tu = ic->textUtil();
68
69 switch ( text_id ) {
70 case UTextArea_Primary:
71 err = tu->acquirePrimaryText( origin, former_req_len, latter_req_len,
72 former, latter );
73 break;
74 case UTextArea_Selection:
75 err = tu->acquireSelectionText( origin, former_req_len, latter_req_len,
76 former, latter );
77 break;
78 case UTextArea_Clipboard:
79 err = tu->acquireClipboardText( origin, former_req_len, latter_req_len,
80 former, latter );
81 break;
82 case UTextArea_Unspecified:
83 default:
84 err = -1;
85 }
86
87 return err;
88 }
89
90 int
delete_text_cb(void * ptr,enum UTextArea text_id,enum UTextOrigin origin,int former_req_len,int latter_req_len)91 QUimTextUtil::delete_text_cb( void *ptr, enum UTextArea text_id,
92 enum UTextOrigin origin,
93 int former_req_len, int latter_req_len )
94 {
95 int err;
96 QUimInputContext *ic = (QUimInputContext *)ptr;
97 QUimTextUtil *tu = ic->textUtil();
98
99 switch ( text_id ) {
100 case UTextArea_Primary:
101 err = tu->deletePrimaryText( origin, former_req_len, latter_req_len );
102 break;
103 case UTextArea_Selection:
104 err = tu->deleteSelectionText( origin, former_req_len, latter_req_len );
105 break;
106 case UTextArea_Clipboard:
107 case UTextArea_Unspecified:
108 default:
109 err = -1;
110 break;
111 }
112
113 return err;
114 }
115
116 int
acquirePrimaryText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)117 QUimTextUtil::acquirePrimaryText( enum UTextOrigin origin,
118 int former_req_len, int latter_req_len,
119 char **former, char **latter )
120 {
121 int err;
122 #if defined(Q_WS_X11)
123 mWidget = mIc->focusWidget();
124 #else
125 return -1;
126 #endif
127
128 if ( mWidget->inherits( "QLineEdit" ) )
129 err = acquirePrimaryTextInQLineEdit( origin, former_req_len,
130 latter_req_len, former, latter );
131 else if ( mWidget->inherits( "QTextEdit" ) )
132 err = acquirePrimaryTextInQTextEdit( origin, former_req_len,
133 latter_req_len, former, latter );
134 else
135 // FIXME other widgets?
136 err = -1;
137
138 return err;
139 }
140
141 int
acquirePrimaryTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)142 QUimTextUtil::acquirePrimaryTextInQLineEdit( enum UTextOrigin origin,
143 int former_req_len,
144 int latter_req_len,
145 char **former, char **latter )
146 {
147 QLineEdit *edit = (QLineEdit *)mWidget;
148 QString text, former_text, latter_text;
149 int cursor_index, len, precedence_len, following_len, offset;
150 int preedit_len, preedit_cursor_pos;
151
152 preedit_len = mIc->getPreeditString().length();
153 preedit_cursor_pos = mIc->getPreeditCursorPosition();
154
155 text = edit->text(); // including preedit string
156 len = text.length();
157 cursor_index = edit->cursorPosition();
158
159 precedence_len = cursor_index - preedit_cursor_pos;
160 following_len = len - precedence_len - preedit_len;
161
162 switch ( origin ) {
163 case UTextOrigin_Cursor:
164 offset = 0;
165 if ( former_req_len >= 0 ) {
166 if ( precedence_len > former_req_len )
167 offset = precedence_len - former_req_len;
168 } else {
169 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
170 return -1;
171 }
172 *former = strdup( text.mid( offset, precedence_len - offset ).utf8() );
173
174 offset = 0;
175 if ( latter_req_len >= 0 ) {
176 if ( following_len > latter_req_len )
177 offset = following_len - latter_req_len;
178 } else {
179 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
180 free( *former );
181 return -1;
182 }
183 }
184 *latter = strdup( text.mid( precedence_len + preedit_len, following_len - offset ).utf8() );
185 break;
186
187 case UTextOrigin_Beginning:
188 *former = NULL;
189 if ( latter_req_len >= 0 ) {
190 if ( precedence_len >= latter_req_len )
191 text = text.left( latter_req_len );
192 else {
193 former_text = text.left( precedence_len );
194 if ( following_len >= ( latter_req_len - precedence_len ) )
195 latter_text = text.mid( precedence_len + preedit_len, ( latter_req_len - precedence_len ) );
196 else
197 latter_text = text.mid( precedence_len + preedit_len, following_len );
198 text = former_text + latter_text;
199 }
200 } else {
201 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
202 return -1;
203
204 former_text = text.left( precedence_len );
205 latter_text = text.mid( precedence_len + preedit_len, following_len );
206 text = former_text + latter_text;
207 }
208 *latter = strdup( text.utf8() );
209 break;
210
211 case UTextOrigin_End:
212 if ( former_req_len >= 0 ) {
213 if ( following_len >= former_req_len )
214 text = text.right( former_req_len );
215 else {
216 latter_text = text.right( following_len );
217 if ( precedence_len >= ( former_req_len - following_len ) )
218 former_text = text.mid( precedence_len - ( former_req_len - following_len ), former_req_len - following_len );
219 else
220 former_text = text.left( precedence_len );
221 text = former_text + latter_text;
222 }
223 } else {
224 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
225 return -1;
226
227 former_text = text.left( precedence_len );
228 latter_text = text.right( following_len );
229 text = former_text + latter_text;
230 }
231 *former = strdup( text.utf8() );
232 *latter = NULL;
233 break;
234
235 case UTextOrigin_Unspecified:
236 default:
237 return -1;
238 }
239
240 return 0;
241 }
242
243 int
acquirePrimaryTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)244 QUimTextUtil::acquirePrimaryTextInQTextEdit( enum UTextOrigin origin,
245 int former_req_len,
246 int latter_req_len,
247 char **former, char **latter )
248 {
249 QTextEdit *edit = (QTextEdit *)mWidget;
250 QString text;
251
252 int i;
253 int start_para, start_index, end_para, end_index, para, index;
254 int n_para;
255 int preedit_len, preedit_cursor_pos;
256 int sel_start_para, sel_start_index, sel_end_para, sel_end_index;
257 TextFormat format;
258
259 format = edit->textFormat();
260 edit->setTextFormat( Qt::PlainText );
261
262 edit->getCursorPosition( ¶, &index ); // including preedit string
263
264 // keep current selection
265 edit->getSelection( &sel_start_para, &sel_start_index, &sel_end_para,
266 &sel_end_index, 0 );
267
268 preedit_len = mIc->getPreeditString().length();
269 preedit_cursor_pos = mIc->getPreeditCursorPosition();
270 n_para = edit->paragraphs();
271
272 switch ( origin ) {
273 case UTextOrigin_Cursor:
274 start_index = index - preedit_cursor_pos;
275 start_para = para;
276 end_index = start_index + preedit_len;
277 end_para = para;
278
279 if ( former_req_len >= 0 ) {
280 for ( i = 0; i < former_req_len; i++ )
281 QTextEditPositionBackward( &start_para, &start_index );
282 } else {
283 if ( former_req_len == UTextExtent_Line )
284 start_index = 0;
285 else if ( former_req_len == UTextExtent_Full ) {
286 start_para = 0;
287 start_index = 0;
288 } else {
289 edit->setTextFormat( format );
290 return -1;
291 }
292 }
293 edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
294 *former = strdup( edit->selectedText().utf8() );
295
296 if ( latter_req_len >= 0 ) {
297 for ( i = 0; i < latter_req_len; i++ )
298 QTextEditPositionForward( &end_para, &end_index );
299 } else {
300 if ( latter_req_len == UTextExtent_Line ) {
301 end_index = edit->paragraphLength( end_para );
302 } else if ( latter_req_len == UTextExtent_Full ) {
303 end_para = n_para - 1;
304 end_index = edit->paragraphLength( end_para );
305 } else {
306 edit->setTextFormat( format );
307 return -1;
308 }
309 }
310 edit->setSelection( para, index - preedit_cursor_pos + preedit_len,
311 end_para, end_index, 0 );
312 *latter = strdup( edit->selectedText().utf8() );
313 break;
314
315 case UTextOrigin_Beginning:
316 *former = NULL;
317
318 start_para = 0;
319 start_index = 0;
320 end_para = start_para;
321 end_index = start_index;
322
323 if ( latter_req_len >= 0 ) {
324 for ( i = 0; i < latter_req_len; i++ )
325 QTextEditPositionForward( &end_para, &end_index );
326 } else {
327 if ( latter_req_len == UTextExtent_Line )
328 end_index = edit->paragraphLength( end_para );
329 else if ( latter_req_len == UTextExtent_Full ) {
330 end_para = n_para - 1;
331 end_index = edit->paragraphLength( end_para );
332 } else {
333 edit->setTextFormat( format );
334 return -1;
335 }
336 }
337 if ( end_para < para || ( end_para == para && end_index <= ( index - preedit_cursor_pos ) ) ) {
338 edit->setSelection( start_para, start_index, end_para, end_index, 0 );
339 text = edit->selectedText();
340 } else {
341 edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
342 text = edit->selectedText();
343 edit->setSelection( para, index - preedit_cursor_pos + preedit_len, end_para, end_index, 0 );
344 text += edit->selectedText();
345 }
346 *latter = strdup( text.utf8() );
347 break;
348
349 case UTextOrigin_End:
350
351 end_para = n_para - 1;
352 end_index = edit->paragraphLength( end_para );
353 start_para = end_para;
354 start_index = end_index;
355
356 if ( former_req_len >= 0 ) {
357 for ( i = 0; i < former_req_len; i++ )
358 QTextEditPositionBackward( &start_para, &start_index );
359 } else {
360 if ( former_req_len == UTextExtent_Line )
361 start_index = 0;
362 else if ( former_req_len == UTextExtent_Full ) {
363 start_para = 0;
364 start_index = 0;
365 } else {
366 edit->setTextFormat( format );
367 return -1;
368 }
369 }
370 if ( start_para > para || ( start_para == para && start_index >= ( index - preedit_cursor_pos + preedit_len ) ) ) {
371 edit->setSelection( start_para, start_index, end_para, end_index, 0 );
372 text = edit->selectedText();
373 } else {
374
375 edit->setSelection( start_para, start_index, para, index - preedit_cursor_pos, 0 );
376 text = edit->selectedText();
377
378 edit->setSelection( para, index - preedit_cursor_pos + preedit_len, end_para, end_index, 0 );
379 text += edit->selectedText();
380 }
381 *former = strdup( text.utf8() );
382 *latter = NULL;
383 break;
384
385 case UTextOrigin_Unspecified:
386 default:
387 edit->setTextFormat( format );
388 return -1;
389 }
390
391 if ( sel_start_para != -1 && sel_start_index != -1 && sel_end_para != -1 &&
392 sel_end_index != -1 )
393 edit->setSelection( sel_start_index, sel_start_index, sel_end_para, sel_end_index, 0 );
394 else
395 edit->removeSelection( 0 );
396
397 edit->setCursorPosition( para, index );
398
399 edit->setTextFormat( format );
400 return 0;
401 }
402
403 int
acquireSelectionText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)404 QUimTextUtil::acquireSelectionText( enum UTextOrigin origin,
405 int former_req_len, int latter_req_len,
406 char **former, char **latter )
407 {
408 int err;
409 #if defined(Q_WS_X11)
410 mWidget = mIc->focusWidget();
411 #else
412 return -1;
413 #endif
414
415 if ( mWidget->inherits( "QLineEdit" ) )
416 err = acquireSelectionTextInQLineEdit( origin, former_req_len,
417 latter_req_len, former, latter );
418 else if ( mWidget->inherits( "QTextEdit" ) )
419 err = acquireSelectionTextInQTextEdit( origin, former_req_len,
420 latter_req_len, former, latter );
421 else
422 // FIXME other widgets?
423 err = -1;
424
425 return err;
426 }
427
428 int
acquireSelectionTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)429 QUimTextUtil::acquireSelectionTextInQLineEdit( enum UTextOrigin origin,
430 int former_req_len,
431 int latter_req_len,
432 char **former, char **latter )
433 {
434 QLineEdit *edit = (QLineEdit *)mWidget;
435 QString text;
436 int len, offset, start, current;
437 bool cursor_at_beginning = false;
438
439 if ( ! edit->hasSelectedText() )
440 return -1;
441
442 current = edit->cursorPosition();
443 start = edit->selectionStart();
444
445 if ( current == start )
446 cursor_at_beginning = true;
447
448 text = edit->selectedText();
449 len = text.length();
450
451 if ( origin == UTextOrigin_Beginning ||
452 ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
453 *former = NULL;
454 offset = 0;
455 if ( latter_req_len >= 0 ) {
456 if ( len > latter_req_len )
457 offset = len - latter_req_len;
458 } else {
459 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
460 return -1;
461 }
462 *latter = strdup( text.left( len - offset ).utf8() );
463 } else if ( origin == UTextOrigin_End ||
464 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
465 offset = 0;
466 if ( former_req_len >= 0 ) {
467 if ( len > former_req_len )
468 offset = len - former_req_len;
469 } else {
470 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
471 return -1;
472 }
473 *former = strdup( text.mid( offset, len - offset ).utf8() );
474 *latter = NULL;
475 } else {
476 return -1;
477 }
478
479 return 0;
480 }
481
482 int
acquireSelectionTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)483 QUimTextUtil::acquireSelectionTextInQTextEdit( enum UTextOrigin origin,
484 int former_req_len,
485 int latter_req_len,
486 char **former, char **latter )
487 {
488 QTextEdit *edit = (QTextEdit *)mWidget;
489 QString text;
490 int len, offset, newline;
491 int start_para, start_index, end_para, end_index;
492 int para, index;
493 bool cursor_at_beginning = false;
494 TextFormat format;
495
496 if ( ! edit->hasSelectedText() )
497 return -1;
498
499 format = edit->textFormat();
500 edit->setTextFormat( Qt::PlainText );
501
502 edit->getCursorPosition( ¶, &index );
503 edit->getSelection(&start_para, &start_index, &end_para, &end_index, 0 );
504
505 if ( para == start_para && index == start_index )
506 cursor_at_beginning = true;
507
508 text = edit->selectedText();
509 len = text.length();
510
511 if ( origin == UTextOrigin_Beginning ||
512 ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
513 *former = NULL;
514 offset = 0;
515 if ( latter_req_len >= 0 ) {
516 if ( len > latter_req_len )
517 offset = len - latter_req_len;
518 } else {
519 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
520 edit->setTextFormat( format );
521 return -1;
522 }
523
524 if ( latter_req_len == UTextExtent_Line && ( ( newline = text.find( '\n' ) ) != -1 ) )
525 offset = len - newline;
526 }
527 *latter = strdup( text.left( len - offset ).utf8() );
528 } else if ( origin == UTextOrigin_End ||
529 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
530 offset = 0;
531 if ( former_req_len >= 0 ) {
532 if ( len > former_req_len )
533 offset = len - former_req_len;
534 } else {
535 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) ) {
536 edit->setTextFormat( format );
537 return -1;
538 }
539
540 if ( former_req_len == UTextExtent_Line && ( ( newline = text.findRev( '\n' ) ) != -1 ) )
541 offset = newline + 1;
542 }
543 *former = strdup( text.mid( offset, len - offset ).utf8() );
544 *latter = NULL;
545 } else {
546 edit->setTextFormat( format );
547 return -1;
548 }
549
550 edit->setTextFormat( format );
551 return 0;
552 }
553
554 int
acquireClipboardText(enum UTextOrigin origin,int former_req_len,int latter_req_len,char ** former,char ** latter)555 QUimTextUtil::acquireClipboardText( enum UTextOrigin origin,
556 int former_req_len, int latter_req_len,
557 char **former, char **latter )
558 {
559 QClipboard *cb = QApplication::clipboard();
560 QString text = cb->text( QClipboard::Clipboard );
561 int len, offset, newline;
562
563 if ( text.isNull() )
564 return -1;
565
566 len = text.length();
567
568 /* Cursor position is assumed to be at the end */
569 switch ( origin ) {
570 case UTextOrigin_Cursor:
571 case UTextOrigin_End:
572 offset = 0;
573 if ( former_req_len >= 0 ) {
574 if ( former_req_len < len )
575 offset = len - former_req_len;
576 } else {
577 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
578 return -1;
579
580 if ( former_req_len == UTextExtent_Line && ( ( newline = text.findRev( '\n' ) ) != -1 ) )
581 offset = newline + 1;
582 }
583 *former = strdup( text.mid( offset, len - offset ).utf8() );
584 *latter = NULL;
585 break;
586
587 case UTextOrigin_Beginning:
588 *former = NULL;
589 offset = 0;
590 if ( latter_req_len >= 0 ) {
591 if ( latter_req_len < len )
592 offset = len - latter_req_len;
593 } else {
594 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
595 return -1;
596
597 if ( latter_req_len == UTextExtent_Line && ( ( newline = text.find( '\n' ) ) != -1 ) )
598 offset = len - newline;
599 }
600 *latter = strdup( text.left( len - offset ).utf8() );
601 break;
602
603 case UTextOrigin_Unspecified:
604 default:
605 return -1;
606 }
607
608 return 0;
609 }
610
611 int
deletePrimaryText(enum UTextOrigin origin,int former_req_len,int latter_req_len)612 QUimTextUtil::deletePrimaryText( enum UTextOrigin origin, int former_req_len,
613 int latter_req_len )
614 {
615 int err;
616 #if defined(Q_WS_X11)
617 mWidget = mIc->focusWidget();
618 #else
619 return -1;
620 #endif
621
622 if ( mWidget->inherits( "QLineEdit" ) )
623 err = deletePrimaryTextInQLineEdit( origin, former_req_len,
624 latter_req_len );
625 else if ( mWidget->inherits( "QTextEdit" ) )
626 err = deletePrimaryTextInQTextEdit( origin, former_req_len,
627 latter_req_len );
628 else
629 // FIXME other widgets?
630 err = -1;
631
632 return err;
633 }
634
635 int
deletePrimaryTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)636 QUimTextUtil::deletePrimaryTextInQLineEdit( enum UTextOrigin origin,
637 int former_req_len,
638 int latter_req_len )
639 {
640 QLineEdit *edit = (QLineEdit *)mWidget;
641 QString text;
642 int cursor_index, len, precedence_len, following_len;
643 int preedit_len, preedit_cursor_pos;
644 int former_del_start;
645 int latter_del_end;
646
647 preedit_len = mIc->getPreeditString().length();
648 preedit_cursor_pos = mIc->getPreeditCursorPosition();
649
650 text = edit->text(); // including preedit string
651 len = text.length();
652 cursor_index = edit->cursorPosition();
653
654 precedence_len = cursor_index - preedit_cursor_pos;
655 following_len = len - precedence_len - preedit_len;
656
657 switch ( origin ) {
658 case UTextOrigin_Cursor:
659 former_del_start = 0;
660 if ( former_req_len >= 0 ) {
661 if ( precedence_len > former_req_len )
662 former_del_start = precedence_len - former_req_len;
663 } else {
664 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
665 return -1;
666 }
667 latter_del_end = len;
668 if ( latter_req_len >= 0 ) {
669 if ( following_len > latter_req_len )
670 latter_del_end = precedence_len + preedit_len + latter_req_len;
671 } else {
672 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
673 return -1;
674 }
675 break;
676
677 case UTextOrigin_Beginning:
678 former_del_start = 0;
679 latter_del_end = precedence_len + preedit_len;
680 if ( latter_req_len >= 0 ) {
681 if ( precedence_len < latter_req_len ) {
682 if ( following_len >= ( latter_req_len - precedence_len ) )
683 latter_del_end = preedit_len + latter_req_len;
684 else
685 latter_del_end = len;
686 }
687 } else {
688 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
689 return -1;
690 latter_del_end = len;
691 }
692 break;
693
694 case UTextOrigin_End:
695 former_del_start = precedence_len;
696 latter_del_end = len;
697 if ( former_req_len < 0 ) {
698 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
699 return -1;
700
701 former_del_start = 0;
702 }
703 break;
704
705 case UTextOrigin_Unspecified:
706 default:
707 return -1;
708 }
709
710 edit->setText( text.left( former_del_start ) + text.right( len - latter_del_end ) );
711 edit->setCursorPosition( former_del_start );
712
713 return 0;
714 }
715
716 int
deletePrimaryTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)717 QUimTextUtil::deletePrimaryTextInQTextEdit( enum UTextOrigin origin,
718 int former_req_len,
719 int latter_req_len )
720 {
721 QTextEdit *edit = (QTextEdit *)mWidget;
722 int i;
723 int start_para, start_index, end_para, end_index, para, index;
724 int n_para;
725
726 savePreedit();
727
728 edit->getCursorPosition( ¶, &index );
729 n_para = edit->paragraphs();
730
731 switch ( origin ) {
732 case UTextOrigin_Cursor:
733 start_index = index;
734 start_para = para;
735 end_index = start_index;
736 end_para = para;
737
738 if ( former_req_len >= 0 ) {
739 for ( i = 0; i < former_req_len; i++ )
740 QTextEditPositionBackward( &start_para, &start_index );
741 } else {
742 if ( former_req_len == UTextExtent_Line ) {
743 start_index = 0;
744 } else if ( former_req_len == UTextExtent_Full ) {
745 start_para = 0;
746 start_index = 0;
747 } else {
748 restorePreedit();
749 return -1;
750 }
751 }
752 if ( latter_req_len >= 0 ) {
753 for ( i = 0; i < latter_req_len; i++ )
754 QTextEditPositionForward( &end_para, &end_index );
755 } else {
756 if ( latter_req_len == UTextExtent_Line ) {
757 end_index = edit->paragraphLength( end_para );
758 } else if ( latter_req_len == UTextExtent_Full ) {
759 end_para = n_para - 1;
760 end_index = edit->paragraphLength( end_para );
761 } else {
762 restorePreedit();
763 return -1;
764 }
765 }
766 break;
767
768 case UTextOrigin_Beginning:
769 start_para = 0;
770 start_index = 0;
771 end_para = start_para;
772 end_index = start_index;
773
774 if ( latter_req_len >= 0 ) {
775 for ( i = 0; i < latter_req_len; i++ )
776 QTextEditPositionForward( &end_para, &end_index );
777 } else {
778 if ( latter_req_len == UTextExtent_Line ) {
779 end_index = edit->paragraphLength( end_para );
780 } else if ( latter_req_len == UTextExtent_Full ) {
781 end_para = n_para - 1;
782 end_index = edit->paragraphLength( end_para );
783 } else {
784 restorePreedit();
785 return -1;
786 }
787 }
788 break;
789
790 case UTextOrigin_End:
791 end_para = n_para - 1;
792 end_index = edit->paragraphLength( end_para );
793 start_para = end_para;
794 start_index = end_index;
795
796 if ( former_req_len >= 0 ) {
797 for ( i = 0; i < former_req_len; i++ )
798 QTextEditPositionBackward( &start_para, &start_index );
799 } else {
800 if ( former_req_len == UTextExtent_Line )
801 start_index = 0;
802 else if ( former_req_len == UTextExtent_Full ) {
803 start_para = 0;
804 start_index = 0;
805 } else {
806 restorePreedit();
807 return -1;
808 }
809 }
810 break;
811
812 case UTextOrigin_Unspecified:
813 default:
814 restorePreedit();
815 return -1;
816 }
817 edit->setSelection( start_para, start_index, end_para, end_index, 1 );
818 edit->removeSelectedText( 1 );
819 edit->setCursorPosition( start_para, start_index );
820 restorePreedit();
821
822 return 0;
823 }
824
825 int
deleteSelectionText(enum UTextOrigin origin,int former_req_len,int latter_req_len)826 QUimTextUtil::deleteSelectionText( enum UTextOrigin origin,
827 int former_req_len, int latter_req_len )
828 {
829 int err;
830 #if defined(Q_WS_X11)
831 mWidget = mIc->focusWidget();
832 #else
833 return -1;
834 #endif
835
836 if ( mWidget->inherits( "QLineEdit" ) )
837 err = deleteSelectionTextInQLineEdit( origin, former_req_len,
838 latter_req_len );
839 else if ( mWidget->inherits( "QTextEdit" ) )
840 err = deleteSelectionTextInQTextEdit( origin, former_req_len,
841 latter_req_len );
842 else
843 // FIXME other widgets?
844 err = -1;
845
846 return err;
847 }
848
849 int
deleteSelectionTextInQLineEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)850 QUimTextUtil::deleteSelectionTextInQLineEdit( enum UTextOrigin origin,
851 int former_req_len,
852 int latter_req_len )
853 {
854 QLineEdit *edit = (QLineEdit *)mWidget;
855 QString text;
856 int len, start, end, current;
857 bool cursor_at_beginning = false;
858
859 if ( ! edit->hasSelectedText() )
860 return -1;
861
862 current = edit->cursorPosition();
863 start = edit->selectionStart();
864 if ( current == start )
865 cursor_at_beginning = true;
866
867 text = edit->selectedText();
868 len = text.length();
869 end = start + len;
870
871 if ( origin == UTextOrigin_Beginning ||
872 ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
873 if ( latter_req_len >= 0 ) {
874 if ( len > latter_req_len )
875 end = start + latter_req_len;
876 } else {
877 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
878 return -1;
879 }
880 } else if ( origin == UTextOrigin_End ||
881 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
882 if ( former_req_len >= 0 ) {
883 if ( len > former_req_len )
884 start = end - former_req_len;
885 } else {
886 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
887 return -1;
888 }
889 } else {
890 return -1;
891 }
892 edit->setSelection( start, end - start );
893 edit->del();
894
895 return 0;
896 }
897
898 int
deleteSelectionTextInQTextEdit(enum UTextOrigin origin,int former_req_len,int latter_req_len)899 QUimTextUtil::deleteSelectionTextInQTextEdit( enum UTextOrigin origin,
900 int former_req_len,
901 int latter_req_len )
902 {
903 QTextEdit *edit = (QTextEdit *)mWidget;
904 QString text;
905 int len, newline, i;
906 int para, index;
907 int sel_para_from, sel_index_from, sel_para_to, sel_index_to;
908 int start_para, start_index, end_para, end_index;
909 bool cursor_at_beginning = false;
910
911 if ( ! edit->hasSelectedText() )
912 return -1;
913
914 edit->getCursorPosition( ¶, &index );
915 edit->getSelection( &sel_para_from, &sel_index_from, &sel_para_to, &sel_index_to, 0 );
916
917 if ( para == sel_para_from && index == sel_index_from )
918 cursor_at_beginning = true;
919
920 text = edit->selectedText();
921 len = text.length();
922
923 start_para = sel_para_from;
924 start_index = sel_index_from;
925 end_para = sel_para_to;
926 end_index = sel_index_to;
927
928 if ( origin == UTextOrigin_Beginning ||
929 ( origin == UTextOrigin_Cursor && cursor_at_beginning ) ) {
930 edit->setCursorPosition( sel_para_from, sel_index_from );
931 if ( latter_req_len >= 0 ) {
932 if ( len > latter_req_len ) {
933 end_para = sel_para_from;
934 end_index = sel_index_from;
935 for ( i = 0; i < latter_req_len; i++)
936 QTextEditPositionForward( &end_para, &end_index );
937 }
938 } else {
939 if (! ( ~latter_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
940 return -1;
941
942 if ( latter_req_len == UTextExtent_Line && ( ( newline = text.find('\n') ) != -1 ) ) {
943 end_para = sel_para_from;
944 end_index = sel_index_from + newline;
945 }
946 }
947 } else if ( origin == UTextOrigin_End ||
948 ( origin == UTextOrigin_Cursor && !cursor_at_beginning ) ) {
949 if ( former_req_len >= 0 ) {
950 if ( len > former_req_len ) {
951 start_para = sel_para_to;
952 start_index = sel_index_to;
953 for ( i = 0; i < former_req_len; i++)
954 QTextEditPositionBackward( &start_para, &start_index );
955 }
956 } else {
957 if (! ( ~former_req_len & ( ~UTextExtent_Line | ~UTextExtent_Full ) ) )
958 return -1;
959
960 if ( former_req_len == UTextExtent_Line && ( ( newline = text.findRev( '\n' ) ) != -1 ) ) {
961 start_para = sel_para_to;
962 start_index = 0;
963 }
964 }
965 } else {
966 return -1;
967 }
968 edit->setSelection( start_para, start_index, end_para, end_index, 1 );
969 edit->removeSelectedText( 1 );
970
971 return 0;
972 }
973
974 void
QTextEditPositionBackward(int * cursor_para,int * cursor_index)975 QUimTextUtil::QTextEditPositionBackward( int *cursor_para, int *cursor_index )
976 {
977 QTextEdit *edit = (QTextEdit *)mWidget;
978 int preedit_len, preedit_cursor_pos;
979 int para, index;
980 int current_para, current_index;
981
982 current_para = *cursor_para;
983 current_index = *cursor_index;
984
985 if ( ! mPreeditSaved ) {
986 preedit_len = mIc->getPreeditString().length();
987 preedit_cursor_pos = mIc->getPreeditCursorPosition();
988 } else {
989 preedit_len = 0;
990 preedit_cursor_pos = 0;
991 }
992 edit->getCursorPosition( ¶, &index );
993
994 if ( current_para == para && current_index > ( index - preedit_cursor_pos ) && ( current_index <= ( index - preedit_cursor_pos + preedit_len ) ) )
995 current_index = index - preedit_cursor_pos;
996
997 if ( current_index > 0 )
998 current_index--;
999 else {
1000 if ( current_para > 0 ) {
1001 current_para--;
1002 current_index = edit->paragraphLength( current_para );
1003 }
1004 }
1005
1006 *cursor_para = current_para;
1007 *cursor_index = current_index;
1008 }
1009
1010 void
QTextEditPositionForward(int * cursor_para,int * cursor_index)1011 QUimTextUtil::QTextEditPositionForward( int *cursor_para, int *cursor_index )
1012 {
1013 QTextEdit *edit = (QTextEdit *)mWidget;
1014 int n_para = edit->paragraphs();
1015 int preedit_len, preedit_cursor_pos;
1016 int current_para_len;
1017 int para, index;
1018 int current_para, current_index;
1019
1020 current_para = *cursor_para;
1021 current_index = *cursor_index;
1022
1023 current_para_len = edit->paragraphLength( current_para );
1024 if ( ! mPreeditSaved ) {
1025 preedit_len = mIc->getPreeditString().length();
1026 preedit_cursor_pos = mIc->getPreeditCursorPosition();
1027 } else {
1028 preedit_len = 0;
1029 preedit_cursor_pos = 0;
1030 }
1031 edit->getCursorPosition( ¶, &index );
1032
1033 if ( current_para == para && current_index >= ( index - preedit_cursor_pos ) && current_index < ( index - preedit_cursor_pos + preedit_len ) )
1034 current_index = index - preedit_cursor_pos + preedit_len;
1035
1036 if ( current_para == n_para - 1 ) {
1037 if ( current_index < current_para_len )
1038 current_index++;
1039 } else {
1040 if ( current_index < current_para_len )
1041 current_index++;
1042 else {
1043 current_para++;
1044 current_index = 0;
1045 }
1046 }
1047
1048 *cursor_para = current_para;
1049 *cursor_index = current_index;
1050 }
1051
savePreedit()1052 void QUimTextUtil::savePreedit()
1053 {
1054 mIc->saveContext();
1055 mPreeditSaved = true;
1056 }
1057
restorePreedit()1058 void QUimTextUtil::restorePreedit()
1059 {
1060 mIc->restoreContext();
1061 mPreeditSaved = false;
1062 }
1063
1064 #include "qtextutil.moc"
1065