~ubuntu-branches/ubuntu/hardy/uim/hardy

« back to all changes in this revision

Viewing changes to gtk/text-util.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2007-04-21 03:46:09 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070421034609-gpcurkutp8vaysqj
Tags: 1:1.4.1-3
* Switch to dh_gtkmodules for the gtk 2.10 transition (Closes:
  #419318)
  - debian/control: Add ${misc:Depends} and remove libgtk2.0-bin on
    uim-gtk2.0.
  - debian/uim-gtk2.0.post{inst,rm}: Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
  Copyright (c) 2006-2007 uim Project http://uim.freedesktop.org/
 
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 <config.h>
 
35
 
 
36
#include <gtk/gtk.h>
 
37
#include <glib.h>
 
38
#include <glib/gprintf.h>
 
39
 
 
40
#include <string.h>
 
41
#include <unistd.h>
 
42
 
 
43
#include "uim/uim.h"
 
44
 
 
45
#include "gtk-im-uim.h"
 
46
#include "text-util.h"
 
47
 
 
48
static int
 
49
acquire_text_in_gtk_text_view(GtkTextView *text_view, enum UTextOrigin origin,
 
50
                              int former_req_len, int latter_req_len,
 
51
                              char **former, char **latter)
 
52
{
 
53
  GtkTextIter current, start, end;
 
54
 
 
55
  if (!text_view->buffer)
 
56
    return -1;
 
57
 
 
58
  gtk_text_buffer_get_iter_at_mark(text_view->buffer, &current,
 
59
                                   gtk_text_buffer_get_mark(text_view->buffer,
 
60
                                                            "insert"));
 
61
  switch (origin) {
 
62
  case UTextOrigin_Cursor:
 
63
    start = current;
 
64
    end = current;
 
65
 
 
66
    if (former_req_len >= 0) {
 
67
      gtk_text_iter_backward_chars(&start, former_req_len);
 
68
    } else {
 
69
      if (former_req_len == UTextExtent_Full)
 
70
        gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
71
      else if (former_req_len == UTextExtent_Line)
 
72
        gtk_text_view_backward_display_line_start(text_view, &start);
 
73
      else
 
74
        return -1;
 
75
    }
 
76
    *former = gtk_text_iter_get_slice(&start, &current);
 
77
 
 
78
    if (latter_req_len >= 0)
 
79
      gtk_text_iter_forward_chars(&end, latter_req_len);
 
80
    else {
 
81
      if (latter_req_len == UTextExtent_Full)
 
82
        gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
83
      else if (latter_req_len == UTextExtent_Line)
 
84
        gtk_text_view_forward_display_line_end(text_view, &end);
 
85
      else {
 
86
        g_free(*former);
 
87
        return -1;
 
88
      }
 
89
    }
 
90
    *latter = gtk_text_iter_get_slice(&current, &end);
 
91
    break;
 
92
 
 
93
  case UTextOrigin_Beginning:
 
94
    gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
95
    end = start;
 
96
 
 
97
    *former = NULL;
 
98
 
 
99
    if (latter_req_len >= 0)
 
100
      gtk_text_iter_forward_chars(&end, latter_req_len);
 
101
    else {
 
102
      if (latter_req_len == UTextExtent_Full)
 
103
        gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
104
      else if (latter_req_len == UTextExtent_Line)
 
105
        gtk_text_view_forward_display_line_end(text_view, &end);
 
106
      else
 
107
        return -1;
 
108
    }
 
109
    *latter = gtk_text_iter_get_slice(&start, &end);
 
110
    break;
 
111
 
 
112
  case UTextOrigin_End:
 
113
    gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
114
    start = end;
 
115
 
 
116
    if (former_req_len >= 0) {
 
117
      gtk_text_iter_backward_chars(&start, former_req_len);
 
118
    } else {
 
119
      if (former_req_len == UTextExtent_Full)
 
120
        gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
121
      else if (former_req_len == UTextExtent_Line)
 
122
        gtk_text_view_backward_display_line_start(text_view, &start);
 
123
      else
 
124
        return -1;
 
125
    }
 
126
    *former = gtk_text_iter_get_slice(&start, &end);
 
127
 
 
128
    *latter = NULL;
 
129
    break;
 
130
 
 
131
  case UTextOrigin_Unspecified:
 
132
  default:
 
133
    return -1;
 
134
  }
 
135
 
 
136
  return 0;
 
137
}
 
138
 
 
139
int
 
140
im_uim_acquire_primary_text(IMUIMContext *uic, enum UTextOrigin origin,
 
141
                            int former_req_len, int latter_req_len,
 
142
                            char **former, char **latter)
 
143
{
 
144
  gchar *text, *former_start, *p;
 
145
  gint cursor_index, len, precedence_len, following_len;
 
146
  gboolean success;
 
147
  int offset, err = 0;
 
148
 
 
149
  /*
 
150
   * We may try a specific way for GtkTextView since
 
151
   * gtk_im_context_get_surrounding cannot get text with multiple lines.
 
152
   */
 
153
  if (GTK_IS_TEXT_VIEW(uic->widget))
 
154
    return acquire_text_in_gtk_text_view(GTK_TEXT_VIEW(uic->widget), origin,
 
155
                                         former_req_len, latter_req_len,
 
156
                                         former, latter);
 
157
 
 
158
  /* cursor_index is represented with byte index */
 
159
  success = gtk_im_context_get_surrounding(GTK_IM_CONTEXT(uic), &text,
 
160
                                           &cursor_index);
 
161
  if (!success)
 
162
    return -1;
 
163
 
 
164
  len = strlen(text);
 
165
  precedence_len = g_utf8_strlen(text, cursor_index);
 
166
  following_len = g_utf8_strlen(text + cursor_index, strlen(text) -
 
167
                                cursor_index);
 
168
  switch (origin) {
 
169
  case UTextOrigin_Cursor:
 
170
    offset = 0;
 
171
    if (former_req_len >= 0) {
 
172
      if (precedence_len > former_req_len)
 
173
        offset = precedence_len - former_req_len;
 
174
    } else {
 
175
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
176
        g_free(text);
 
177
        return -1;
 
178
      }
 
179
    }
 
180
    former_start = g_utf8_offset_to_pointer(text, offset);
 
181
    *former = g_strndup(former_start, text - former_start + cursor_index);
 
182
 
 
183
    offset = 0;
 
184
    if (latter_req_len >= 0) {
 
185
      if (following_len > latter_req_len)
 
186
        offset = strlen(g_utf8_offset_to_pointer(text, precedence_len +
 
187
                                                 latter_req_len));
 
188
    } else {
 
189
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
190
        g_free(text);
 
191
        g_free(*former);
 
192
        return -1;
 
193
      }
 
194
    }
 
195
    *latter = g_strndup(text + cursor_index, len - cursor_index - offset);
 
196
    if (latter_req_len == UTextExtent_Line) {
 
197
      gchar *p = strchr(*latter, '\n');
 
198
      if (p)
 
199
        *p = '\0';
 
200
    }
 
201
    break;
 
202
 
 
203
  case UTextOrigin_Beginning:
 
204
    *former = NULL;
 
205
 
 
206
    offset = 0;
 
207
    if (latter_req_len >= 0) {
 
208
      if ((precedence_len + following_len) > latter_req_len)
 
209
        offset = text + len - g_utf8_offset_to_pointer(text, latter_req_len);
 
210
    } else {
 
211
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
212
        g_free(text);
 
213
        return -1;
 
214
      }
 
215
    }
 
216
    *latter = g_strndup(text, len - offset); 
 
217
    if (latter_req_len == UTextExtent_Line &&
 
218
        (p = strchr(*latter, '\n')))
 
219
      *p = '\0';
 
220
    break;
 
221
 
 
222
  case UTextOrigin_End:
 
223
    offset = 0;
 
224
    if (former_req_len >= 0) {
 
225
      if ((precedence_len + following_len) > former_req_len)
 
226
        offset = precedence_len + following_len - former_req_len;
 
227
    } else {
 
228
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
229
        g_free(text);
 
230
        return -1;
 
231
      }
 
232
    }
 
233
    former_start = g_utf8_offset_to_pointer(text, offset);
 
234
    if (former_req_len == UTextExtent_Line &&
 
235
        (p = strrchr(former_start, '\n')))
 
236
      *former = g_strdup(p + 1);
 
237
    else
 
238
      *former = g_strndup(former_start, text + len - former_start);
 
239
 
 
240
    *latter = NULL;
 
241
    break;
 
242
 
 
243
  case UTextOrigin_Unspecified:
 
244
  default:
 
245
    err = -1;
 
246
    break;
 
247
  }
 
248
  g_free(text);
 
249
 
 
250
  return err;
 
251
}
 
252
 
 
253
int
 
254
im_uim_acquire_selection_text(IMUIMContext *uic, enum UTextOrigin origin,
 
255
                              int former_req_len, int latter_req_len,
 
256
                              char **former, char **latter)
 
257
{
 
258
  gchar *former_start, *text = NULL, *p;
 
259
  gint len, text_len;
 
260
  int offset, err = 0;
 
261
  gboolean cursor_at_beginning = FALSE;
 
262
 
 
263
  if (GTK_IS_ENTRY(uic->widget)) {
 
264
    gint start, end, current;
 
265
 
 
266
    if (gtk_editable_get_selection_bounds(GTK_EDITABLE(uic->widget),
 
267
                                          &start, &end)) {
 
268
      text = gtk_editable_get_chars(GTK_EDITABLE(uic->widget), start, end);
 
269
      current = GTK_ENTRY(uic->widget)->current_pos;
 
270
      if (current == start)
 
271
        cursor_at_beginning = TRUE;
 
272
    }
 
273
  } else if (GTK_IS_TEXT_VIEW(uic->widget)) {
 
274
    GtkTextIter start, end, current;
 
275
 
 
276
    if (GTK_TEXT_VIEW(uic->widget)->buffer &&
 
277
        gtk_text_buffer_get_selection_bounds(GTK_TEXT_VIEW(uic->widget)->buffer, &start, &end)) {
 
278
      text = gtk_text_iter_get_visible_text(&start, &end);
 
279
      gtk_text_buffer_get_iter_at_mark(GTK_TEXT_VIEW(uic->widget)->buffer,
 
280
                                       &current,
 
281
                                       gtk_text_buffer_get_mark(GTK_TEXT_VIEW(uic->widget)->buffer, "insert"));
 
282
      if (gtk_text_iter_compare(&start, &current) == 0)
 
283
        cursor_at_beginning = TRUE;
 
284
    }
 
285
  } else {
 
286
    /*
 
287
     * We use GDK_SELECTION_PRIMARY for the rest of widget, which means it is
 
288
     * impossible to guarantee whether the obtained one is the selected text on
 
289
     * the target application.
 
290
     */ 
 
291
    text = gtk_clipboard_wait_for_text(gtk_widget_get_clipboard(GTK_WIDGET(uic->widget), GDK_SELECTION_PRIMARY));
 
292
  }
 
293
 
 
294
  if (!text)
 
295
    return -1;
 
296
 
 
297
  len = strlen(text);
 
298
  text_len = g_utf8_strlen(text, -1);
 
299
 
 
300
  if (origin == UTextOrigin_Beginning ||
 
301
      (origin == UTextOrigin_Cursor && cursor_at_beginning)) {
 
302
    *former = NULL;
 
303
 
 
304
    offset = 0;
 
305
    if (latter_req_len >= 0) {
 
306
      if (latter_req_len < text_len)
 
307
        offset = text + len - g_utf8_offset_to_pointer(text, latter_req_len);
 
308
    } else {
 
309
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
310
        g_free(text);
 
311
        return -1;
 
312
      }
 
313
    }
 
314
    *latter = g_strndup(text, len - offset);
 
315
    if (latter_req_len == UTextExtent_Line && (p = strchr(*latter, '\n')))
 
316
      *p = '\0';
 
317
 
 
318
  } else if (origin == UTextOrigin_End ||
 
319
             (origin == UTextOrigin_Cursor && !cursor_at_beginning)) {
 
320
    offset = 0;
 
321
    if (former_req_len >= 0) {
 
322
      if (former_req_len < text_len)
 
323
        offset = text_len - former_req_len;
 
324
    } else {
 
325
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
326
        g_free(text);
 
327
        return -1;
 
328
      }
 
329
    }
 
330
    former_start = g_utf8_offset_to_pointer(text, offset);
 
331
    if (former_req_len == UTextExtent_Line &&
 
332
        (p = strrchr(former_start, '\n')))
 
333
      *former = g_strdup(p + 1);
 
334
    else
 
335
      *former = g_strndup(former_start, text + len - former_start);
 
336
 
 
337
    *latter = NULL;
 
338
 
 
339
  } else {
 
340
    err = -1;
 
341
  }
 
342
  g_free(text);
 
343
 
 
344
  return err;
 
345
}
 
346
 
 
347
int
 
348
im_uim_acquire_clipboard_text(IMUIMContext *uic, enum UTextOrigin origin,
 
349
                              int former_req_len, int latter_req_len,
 
350
                              char **former, char **latter)
 
351
{
 
352
  gchar *former_start, *text = NULL, *p;
 
353
  gint len, text_len;
 
354
  int offset, err = 0;
 
355
 
 
356
  text = gtk_clipboard_wait_for_text(gtk_widget_get_clipboard(GTK_WIDGET(uic->widget), GDK_SELECTION_CLIPBOARD));
 
357
 
 
358
  if (!text)
 
359
    return -1;
 
360
 
 
361
  len = strlen(text);
 
362
  text_len = g_utf8_strlen(text, -1);
 
363
 
 
364
  /* treat cursor position is virtually at the end for UTextArea_Clipboard */
 
365
  switch (origin) {
 
366
  case UTextOrigin_Cursor:
 
367
  case UTextOrigin_End:
 
368
    offset = 0;
 
369
    if (former_req_len >= 0) {
 
370
      if (former_req_len < text_len)
 
371
        offset = text_len - former_req_len;
 
372
    } else {
 
373
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
374
        g_free(text);
 
375
        return -1;
 
376
      }
 
377
    }
 
378
    former_start = g_utf8_offset_to_pointer(text, offset);
 
379
    if (former_req_len == UTextExtent_Line &&
 
380
        (p = strrchr(former_start, '\n')))
 
381
      *former = g_strdup(p + 1);
 
382
    else
 
383
      *former = g_strndup(former_start, text + len - former_start);
 
384
    *latter = NULL;
 
385
    break;
 
386
  case UTextOrigin_Beginning:
 
387
    offset = 0;
 
388
    if (latter_req_len >= 0) {
 
389
      if (latter_req_len < text_len)
 
390
        offset = text + len - g_utf8_offset_to_pointer(text, latter_req_len);
 
391
    } else {
 
392
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) {
 
393
        g_free(text);
 
394
        return -1;
 
395
      }
 
396
      if (latter_req_len == UTextExtent_Line && (p = strchr(text, '\n')))
 
397
        offset = text + len - p;
 
398
    }
 
399
    *latter = g_strndup(text, len - offset);
 
400
    *former = NULL;
 
401
    break;
 
402
  case UTextOrigin_Unspecified:
 
403
  default:
 
404
    err = -1;
 
405
    break;
 
406
  }
 
407
  g_free(text);
 
408
 
 
409
  return err;
 
410
}
 
411
 
 
412
static int
 
413
delete_text_in_gtk_entry(GtkEntry *entry, enum UTextOrigin origin,
 
414
                         int former_req_len, int latter_req_len)
 
415
{
 
416
  gint start_pos, end_pos, current_pos;
 
417
 
 
418
  current_pos = entry->current_pos;
 
419
 
 
420
  switch (origin) {
 
421
  case UTextOrigin_Cursor:
 
422
    if (former_req_len >= 0) {
 
423
      start_pos = current_pos - former_req_len;
 
424
    } else {
 
425
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
426
        return -1;
 
427
      start_pos = 0;
 
428
    }
 
429
 
 
430
    if (latter_req_len >= 0)
 
431
      end_pos = current_pos + latter_req_len;
 
432
    else {
 
433
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
434
        return -1;
 
435
      end_pos = entry->text_length;
 
436
    }
 
437
    break;
 
438
 
 
439
  case UTextOrigin_Beginning:
 
440
    start_pos = 0;
 
441
 
 
442
    if (latter_req_len >= 0)
 
443
      end_pos = latter_req_len;
 
444
    else {
 
445
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
446
        return -1;
 
447
      end_pos = entry->text_length;
 
448
    }
 
449
    break;
 
450
 
 
451
  case UTextOrigin_End:
 
452
    if (former_req_len >= 0)
 
453
      start_pos = entry->text_length - former_req_len;
 
454
    else {
 
455
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
456
        return -1;
 
457
      start_pos = 0;
 
458
    }
 
459
 
 
460
    end_pos = entry->text_length;
 
461
    break;
 
462
 
 
463
  case UTextOrigin_Unspecified:
 
464
  default:
 
465
    return -1;
 
466
  }
 
467
 
 
468
  gtk_editable_delete_text(GTK_EDITABLE(entry), start_pos, end_pos);
 
469
 
 
470
  return 0;
 
471
}
 
472
 
 
473
static int
 
474
delete_text_in_gtk_text_view(GtkTextView *text_view, enum UTextOrigin origin,
 
475
                             int former_req_len, int latter_req_len)
 
476
{
 
477
  GtkTextIter current, start, end;
 
478
 
 
479
  if (!text_view->buffer)
 
480
    return -1;
 
481
 
 
482
  gtk_text_buffer_get_iter_at_mark(text_view->buffer, &current,
 
483
                                   gtk_text_buffer_get_mark(text_view->buffer,
 
484
                                                            "insert"));
 
485
  start = current;
 
486
  end = current;
 
487
 
 
488
  switch (origin) {
 
489
  case UTextOrigin_Cursor:
 
490
    if (former_req_len >= 0) {
 
491
      gtk_text_iter_backward_chars(&start, former_req_len);
 
492
    } else {
 
493
      if (former_req_len == UTextExtent_Full)
 
494
        gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
495
      else if (former_req_len == UTextExtent_Line)
 
496
        gtk_text_view_backward_display_line_start(text_view, &start);
 
497
      else
 
498
        return -1;
 
499
    }
 
500
 
 
501
    if (latter_req_len >= 0)
 
502
      gtk_text_iter_forward_chars(&end, latter_req_len);
 
503
    else {
 
504
      if (latter_req_len == UTextExtent_Full)
 
505
        gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
506
      else if (latter_req_len == UTextExtent_Line)
 
507
        gtk_text_view_forward_display_line_end(text_view, &end);
 
508
      else
 
509
        return -1;
 
510
    }
 
511
    break;
 
512
 
 
513
  case UTextOrigin_Beginning:
 
514
    gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
515
    end = start;
 
516
 
 
517
    if (latter_req_len >= 0)
 
518
      gtk_text_iter_forward_chars(&end, latter_req_len);
 
519
    else {
 
520
      if (latter_req_len == UTextExtent_Full)
 
521
        gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
522
      else if (latter_req_len == UTextExtent_Line)
 
523
        gtk_text_view_forward_display_line_end(text_view, &end);
 
524
      else
 
525
        return -1;
 
526
    }
 
527
    break;
 
528
 
 
529
  case UTextOrigin_End:
 
530
    gtk_text_buffer_get_end_iter(text_view->buffer, &end);
 
531
    start = end;
 
532
 
 
533
    if (former_req_len >= 0) {
 
534
      gtk_text_iter_backward_chars(&start, former_req_len);
 
535
    } else {
 
536
      if (former_req_len == UTextExtent_Full)
 
537
        gtk_text_buffer_get_start_iter(text_view->buffer, &start);
 
538
      else if (former_req_len == UTextExtent_Line)
 
539
        gtk_text_view_backward_display_line_start(text_view, &start);
 
540
      else
 
541
        return -1;
 
542
    }
 
543
    break;
 
544
 
 
545
  case UTextOrigin_Unspecified:
 
546
  default:
 
547
    return -1;
 
548
  }
 
549
 
 
550
  gtk_text_buffer_delete_interactive(text_view->buffer, &start, &end,
 
551
                                     text_view->editable);
 
552
 
 
553
  return 0;
 
554
}
 
555
 
 
556
int
 
557
im_uim_delete_primary_text(IMUIMContext *uic, enum UTextOrigin origin,
 
558
                           int former_req_len, int latter_req_len)
 
559
{
 
560
  gboolean success;
 
561
  gint offset, n_chars;
 
562
 
 
563
  /* specific widgets handling */
 
564
  if (GTK_IS_ENTRY(uic->widget))
 
565
    return delete_text_in_gtk_entry(GTK_ENTRY(uic->widget), origin,
 
566
                                    former_req_len, latter_req_len);
 
567
  else if (GTK_IS_TEXT_VIEW(uic->widget))
 
568
    return delete_text_in_gtk_text_view(GTK_TEXT_VIEW(uic->widget), origin,
 
569
                                        former_req_len, latter_req_len);
 
570
  /*
 
571
   * For the rest of widget, we use delete_surrounding, which  means explicit
 
572
   * value for former_len and latter_len is required and its origin must be the
 
573
   * cursor.
 
574
   */
 
575
  offset = n_chars = 0;
 
576
 
 
577
  switch (origin) {
 
578
  case UTextOrigin_Cursor:
 
579
    if (former_req_len >= 0) {
 
580
      offset = -former_req_len;
 
581
      n_chars = former_req_len;
 
582
    } else {
 
583
        return -1;
 
584
    }
 
585
 
 
586
    if (latter_req_len >= 0)
 
587
      n_chars += latter_req_len;
 
588
    else
 
589
      return -1;
 
590
    break;
 
591
 
 
592
  case UTextOrigin_Beginning:
 
593
  case UTextOrigin_End:
 
594
  case UTextOrigin_Unspecified:
 
595
  default:
 
596
    return -1;
 
597
  }
 
598
 
 
599
  success = gtk_im_context_delete_surrounding(GTK_IM_CONTEXT(uic), offset,
 
600
                                              n_chars);
 
601
  return success ? 0 : -1;
 
602
}
 
603
 
 
604
static int
 
605
delete_selection_in_gtk_entry(GtkEntry *entry, enum UTextOrigin origin,
 
606
                              int former_req_len, int latter_req_len)
 
607
{
 
608
  gint start, end, current_pos;
 
609
  gboolean cursor_at_beginning = FALSE;
 
610
 
 
611
  if (!gtk_editable_get_selection_bounds(GTK_EDITABLE(entry), &start, &end))
 
612
    return -1;
 
613
 
 
614
  current_pos = entry->current_pos;
 
615
  if (current_pos == start)
 
616
    cursor_at_beginning = TRUE;
 
617
 
 
618
  if (origin == UTextOrigin_Beginning ||
 
619
      (origin == UTextOrigin_Cursor && cursor_at_beginning)) {
 
620
    if (latter_req_len >= 0) {
 
621
      if (latter_req_len < end - start)
 
622
        end = start + latter_req_len;
 
623
    } else {
 
624
      if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
625
        return -1;
 
626
    }
 
627
  } else if (origin == UTextOrigin_End ||
 
628
             (origin == UTextOrigin_Cursor && !cursor_at_beginning)) {
 
629
    if (former_req_len >= 0) {
 
630
      if (former_req_len < end - start)
 
631
        start = end - former_req_len;
 
632
    } else {
 
633
      if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full)))
 
634
        return -1;
 
635
    }
 
636
  } else {
 
637
    return -1;
 
638
  }
 
639
 
 
640
  gtk_editable_delete_text(GTK_EDITABLE(entry), start, end);
 
641
 
 
642
  return 0;
 
643
}
 
644
 
 
645
static int
 
646
delete_selection_in_gtk_text_view(GtkTextView *text_view,
 
647
                                  enum UTextOrigin origin, int former_req_len,
 
648
                                  int latter_req_len)
 
649
{
 
650
  GtkTextIter current, start, end, tmp_start, tmp_end;
 
651
  gboolean cursor_at_beginning = FALSE;
 
652
 
 
653
  if (!text_view->buffer)
 
654
    return -1;
 
655
 
 
656
  if (gtk_text_buffer_get_selection_bounds(text_view->buffer, &start, &end)) {
 
657
    gtk_text_buffer_get_iter_at_mark(text_view->buffer, &current,
 
658
                                     gtk_text_buffer_get_mark(text_view->buffer, "insert"));
 
659
    if (gtk_text_iter_compare(&start, &current) == 0)
 
660
      cursor_at_beginning = TRUE;
 
661
  } else {
 
662
    return -1;
 
663
  }
 
664
 
 
665
  if (origin == UTextOrigin_Beginning ||
 
666
      (origin == UTextOrigin_Cursor && cursor_at_beginning)) {
 
667
    tmp_start = start;
 
668
    tmp_end = start;
 
669
 
 
670
    if (latter_req_len >= 0) {
 
671
      gtk_text_iter_forward_chars(&tmp_end, latter_req_len);
 
672
      if (gtk_text_iter_compare(&tmp_end, &end) < 0)
 
673
        end = tmp_end;
 
674
    } else {
 
675
      if (latter_req_len == UTextExtent_Line) {
 
676
        gtk_text_view_forward_display_line_end(text_view, &tmp_end);
 
677
        if (gtk_text_iter_compare(&tmp_end, &end) < 0)
 
678
          end = tmp_end;
 
679
      } else {
 
680
        if (!(latter_req_len == UTextExtent_Full))
 
681
          return -1;
 
682
      }
 
683
    }
 
684
 
 
685
  } else if (origin == UTextOrigin_End ||
 
686
             (origin == UTextOrigin_Cursor && !cursor_at_beginning)) {
 
687
    tmp_start = end;
 
688
    tmp_end = end;
 
689
 
 
690
    if (former_req_len >= 0) {
 
691
      gtk_text_iter_backward_chars(&tmp_start, former_req_len);
 
692
      if (gtk_text_iter_compare(&tmp_start, &start) > 0)
 
693
        start = tmp_start;
 
694
    } else {
 
695
      if (former_req_len == UTextExtent_Line) {
 
696
        gtk_text_view_backward_display_line_start(text_view, &tmp_start);
 
697
        if (gtk_text_iter_compare(&tmp_start, &start) > 0)
 
698
          start = tmp_start;
 
699
      } else {
 
700
        if (!(former_req_len == UTextExtent_Full))
 
701
          return -1;
 
702
      }
 
703
    }
 
704
 
 
705
  } else {
 
706
    return -1;
 
707
  }
 
708
 
 
709
  gtk_text_buffer_delete_interactive(text_view->buffer, &start, &end,
 
710
                                     text_view->editable);
 
711
 
 
712
  return 0;
 
713
}
 
714
 
 
715
int
 
716
im_uim_delete_selection_text(IMUIMContext *uic, enum UTextOrigin origin,
 
717
                             int former_req_len, int latter_req_len)
 
718
{
 
719
  /* specific widgets handling */
 
720
  if (GTK_IS_ENTRY(uic->widget))
 
721
    return delete_selection_in_gtk_entry(GTK_ENTRY(uic->widget), origin,
 
722
                                    former_req_len, latter_req_len);
 
723
  else if (GTK_IS_TEXT_VIEW(uic->widget))
 
724
    return delete_selection_in_gtk_text_view(GTK_TEXT_VIEW(uic->widget), origin,
 
725
                                        former_req_len, latter_req_len);
 
726
  /*
 
727
   * How can we delete a selected text?
 
728
   * We just expect the selected text will be overridden by a newly committed
 
729
   * text.
 
730
   */
 
731
  
 
732
  return -1;
 
733
}