]> Pileus Git - ~andy/gtk/blob - gtk/gtkimcontext.c
Change FSF Address
[~andy/gtk] / gtk / gtkimcontext.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include <string.h>
20 #include "gtkimcontext.h"
21 #include "gtkprivate.h"
22 #include "gtkmarshalers.h"
23 #include "gtkintl.h"
24
25 /**
26  * SECTION:gtkimcontext
27  * @title: GtkIMContext
28  * @short_description: Base class for input method contexts
29  * @include: gtk/gtk.h,gtk/gtkimmodule.h
30  *
31  * #GtkIMContext defines the interface for GTK+ input methods. An input method
32  * is used by GTK+ text input widgets like #GtkEntry to map from key events to
33  * Unicode character strings.
34  *
35  * The user may change the current input method via a context menu, unless the   
36  * #GtkSettings:gtk-show-input-method-menu GtkSettings property is set to FALSE. 
37  * The default input method can be set programmatically via the 
38  * #GtkSettings:gtk-im-module GtkSettings property. Alternatively, you may set 
39  * the GTK_IM_MODULE environment variable as documented in #gtk-running.
40  *
41  * The #GtkEntry #GtkEntry:im-module and #GtkTextView #GtkTextView:im-module 
42  * properties may also be used to set input methods for specific widget 
43  * instances. For instance, a certain entry widget might be expected to contain 
44  * certain characters which would be easier to input with a certain input 
45  * method.
46  *
47  * An input method may consume multiple key events in sequence and finally
48  * output the composed result. This is called preediting, and an input method
49  * may provide feedback about this process by displaying the intermediate
50  * composition states as preedit text. For instance, the default GTK+ input
51  * method implements the input of arbitrary Unicode code points by holding down
52  * the Control and Shift keys and then typing "U" followed by the hexadecimal
53  * digits of the code point.  When releasing the Control and Shift keys,
54  * preediting ends and the character is inserted as text. Ctrl+Shift+u20AC for
55  * example results in the € sign.
56  *
57  * Additional input methods can be made available for use by GTK+ widgets as
58  * loadable modules. An input method module is a small shared library which
59  * implements a subclass of #GtkIMContext or #GtkIMContextSimple and exports
60  * these four functions:
61  *
62  * <informalexample><programlisting>
63  * void im_module_init(#GTypeModule *module);
64  * </programlisting></informalexample>
65  * This function should register the #GType of the #GtkIMContext subclass which
66  * implements the input method by means of g_type_module_register_type(). Note
67  * that g_type_register_static() cannot be used as the type needs to be
68  * registered dynamically.
69  *
70  * <informalexample><programlisting>
71  * void im_module_exit(void);
72  * </programlisting></informalexample>
73  * Here goes any cleanup code your input method might require on module unload.
74  *
75  * <informalexample><programlisting>
76  * void im_module_list(const #GtkIMContextInfo ***contexts, int *n_contexts)
77  * {
78  *   *contexts = info_list;
79  *   *n_contexts = G_N_ELEMENTS (info_list);
80  * }
81  * </programlisting></informalexample>
82  * This function returns the list of input methods provided by the module. The
83  * example implementation above shows a common solution and simply returns a
84  * pointer to statically defined array of #GtkIMContextInfo items for each
85  * provided input method.
86  *
87  * <informalexample><programlisting>
88  * #GtkIMContext * im_module_create(const #gchar *context_id);
89  * </programlisting></informalexample>
90  * This function should return a pointer to a newly created instance of the
91  * #GtkIMContext subclass identified by @context_id. The context ID is the same
92  * as specified in the #GtkIMContextInfo array returned by im_module_list().
93  *
94  * After a new loadable input method module has been installed on the system,
95  * the configuration file <filename>gtk.immodules</filename> needs to be
96  * regenerated by <link linkend="gtk-query-immodules-3.0">gtk-query-immodules-3.0</link>,
97  * in order for the new input method to become available to GTK+ applications.
98  */
99
100 enum {
101   PREEDIT_START,
102   PREEDIT_END,
103   PREEDIT_CHANGED,
104   COMMIT,
105   RETRIEVE_SURROUNDING,
106   DELETE_SURROUNDING,
107   LAST_SIGNAL
108 };
109
110 static guint im_context_signals[LAST_SIGNAL] = { 0 };
111
112 static void     gtk_im_context_real_get_preedit_string (GtkIMContext   *context,
113                                                         gchar         **str,
114                                                         PangoAttrList **attrs,
115                                                         gint           *cursor_pos);
116 static gboolean gtk_im_context_real_filter_keypress    (GtkIMContext   *context,
117                                                         GdkEventKey    *event);
118 static gboolean gtk_im_context_real_get_surrounding    (GtkIMContext   *context,
119                                                         gchar         **text,
120                                                         gint           *cursor_index);
121 static void     gtk_im_context_real_set_surrounding    (GtkIMContext   *context,
122                                                         const char     *text,
123                                                         gint            len,
124                                                         gint            cursor_index);
125
126 G_DEFINE_ABSTRACT_TYPE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT)
127
128 /**
129  * GtkIMContextClass:
130  * @preedit_start: Default handler of the #GtkIMContext::preedit-start signal.
131  * @preedit_end: Default handler of the #GtkIMContext::preedit-end signal.
132  * @preedit_changed: Default handler of the #GtkIMContext::preedit-changed
133  *   signal.
134  * @commit: Default handler of the #GtkIMContext::commit signal.
135  * @retrieve_surrounding: Default handler of the
136  *   #GtkIMContext::retrieve-surrounding signal.
137  * @delete_surrounding: Default handler of the
138  *   #GtkIMContext::delete-surrounding signal.
139  * @set_client_window: Called via gtk_im_context_set_client_window() when the
140  *   input window where the entered text will appear changes. Override this to
141  *   keep track of the current input window, for instance for the purpose of
142  *   positioning a status display of your input method.
143  * @get_preedit_string: Called via gtk_im_context_get_preedit_string() to
144  *   retrieve the text currently being preedited for display at the cursor
145  *   position. Any input method which composes complex characters or any
146  *   other compositions from multiple sequential key presses should override
147  *   this method to provide feedback.
148  * @filter_keypress: Called via gtk_im_context_filter_keypress() on every
149  *   key press or release event. Every non-trivial input method needs to
150  *   override this in order to implement the mapping from key events to text.
151  *   A return value of %TRUE indicates to the caller that the event was
152  *   consumed by the input method. In that case, the #GtkIMContext::commit
153  *   signal should be emitted upon completion of a key sequence to pass the
154  *   resulting text back to the input widget. Alternatively, %FALSE may be
155  *   returned to indicate that the event wasn't handled by the input method.
156  *   If a builtin mapping exists for the key, it is used to produce a
157  *   character.
158  * @focus_in: Called via gtk_im_context_focus_in() when the input widget
159  *   has gained focus. May be overridden to keep track of the current focus.
160  * @focus_out: Called via gtk_im_context_focus_out() when the input widget
161  *   has lost focus. May be overridden to keep track of the current focus.
162  * @reset: Called via gtk_im_context_reset() to signal a change such as a
163  *   change in cursor position. An input method that implements preediting
164  *   should override this method to clear the preedit state on reset.
165  * @set_cursor_location: Called via gtk_im_context_set_cursor_location()
166  *   to inform the input method of the current cursor location relative to
167  *   the client window. May be overridden to implement the display of popup
168  *   windows at the cursor position.
169  * @set_use_preedit: Called via gtk_im_context_set_use_preedit() to control
170  *   the use of the preedit string. Override this to display feedback by some
171  *   other means if turned off.
172  * @set_surrounding: Called via gtk_im_context_set_surrounding() in response
173  *   to signal #GtkIMContext::retrieve-surrounding to update the input
174  *   method's idea of the context around the cursor. It is not necessary to
175  *   override this method even with input methods which implement
176  *   context-dependent behavior. The base implementation is sufficient for
177  *   gtk_im_context_get_surrounding() to work.
178  * @get_surrounding: Called via gtk_im_context_get_surrounding() to update
179  *   the context around the cursor location. It is not necessary to override
180  *   this method even with input methods which implement context-dependent
181  *   behavior. The base implementation emits
182  *   #GtkIMContext::retrieve-surrounding and records the context received
183  *   by the subsequent invocation of @get_surrounding.
184  */
185 static void
186 gtk_im_context_class_init (GtkIMContextClass *klass)
187 {
188   klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
189   klass->filter_keypress = gtk_im_context_real_filter_keypress;
190   klass->get_surrounding = gtk_im_context_real_get_surrounding;
191   klass->set_surrounding = gtk_im_context_real_set_surrounding;
192
193   /**
194    * GtkIMContext::preedit-start:
195    * @context: the object on which the signal is emitted
196    *
197    * The ::preedit-start signal is emitted when a new preediting sequence
198    * starts.
199    */
200   im_context_signals[PREEDIT_START] =
201     g_signal_new (I_("preedit-start"),
202                   G_TYPE_FROM_CLASS (klass),
203                   G_SIGNAL_RUN_LAST,
204                   G_STRUCT_OFFSET (GtkIMContextClass, preedit_start),
205                   NULL, NULL,
206                   _gtk_marshal_VOID__VOID,
207                   G_TYPE_NONE, 0);
208   /**
209    * GtkIMContext::preedit-end:
210    * @context: the object on which the signal is emitted
211    *
212    * The ::preedit-end signal is emitted when a preediting sequence
213    * has been completed or canceled.
214    */
215   im_context_signals[PREEDIT_END] =
216     g_signal_new (I_("preedit-end"),
217                   G_TYPE_FROM_CLASS (klass),
218                   G_SIGNAL_RUN_LAST,
219                   G_STRUCT_OFFSET (GtkIMContextClass, preedit_end),
220                   NULL, NULL,
221                   _gtk_marshal_VOID__VOID,
222                   G_TYPE_NONE, 0);
223   /**
224    * GtkIMContext::preedit-changed:
225    * @context: the object on which the signal is emitted
226    *
227    * The ::preedit-changed signal is emitted whenever the preedit sequence
228    * currently being entered has changed.  It is also emitted at the end of
229    * a preedit sequence, in which case
230    * gtk_im_context_get_preedit_string() returns the empty string.
231    */
232   im_context_signals[PREEDIT_CHANGED] =
233     g_signal_new (I_("preedit-changed"),
234                   G_TYPE_FROM_CLASS (klass),
235                   G_SIGNAL_RUN_LAST,
236                   G_STRUCT_OFFSET (GtkIMContextClass, preedit_changed),
237                   NULL, NULL,
238                   _gtk_marshal_VOID__VOID,
239                   G_TYPE_NONE, 0);
240   /**
241    * GtkIMContext::commit:
242    * @context: the object on which the signal is emitted
243    * @str: the completed character(s) entered by the user
244    *
245    * The ::commit signal is emitted when a complete input sequence
246    * has been entered by the user. This can be a single character
247    * immediately after a key press or the final result of preediting.
248    */
249   im_context_signals[COMMIT] =
250     g_signal_new (I_("commit"),
251                   G_TYPE_FROM_CLASS (klass),
252                   G_SIGNAL_RUN_LAST,
253                   G_STRUCT_OFFSET (GtkIMContextClass, commit),
254                   NULL, NULL,
255                   _gtk_marshal_VOID__STRING,
256                   G_TYPE_NONE, 1,
257                   G_TYPE_STRING);
258   /**
259    * GtkIMContext::retrieve-surrounding:
260    * @context: the object on which the signal is emitted
261    *
262    * The ::retrieve-surrounding signal is emitted when the input method
263    * requires the context surrounding the cursor.  The callback should set
264    * the input method surrounding context by calling the
265    * gtk_im_context_set_surrounding() method.
266    *
267    * Return value: %TRUE if the signal was handled.
268    */
269   im_context_signals[RETRIEVE_SURROUNDING] =
270     g_signal_new (I_("retrieve-surrounding"),
271                   G_TYPE_FROM_CLASS (klass),
272                   G_SIGNAL_RUN_LAST,
273                   G_STRUCT_OFFSET (GtkIMContextClass, retrieve_surrounding),
274                   _gtk_boolean_handled_accumulator, NULL,
275                   _gtk_marshal_BOOLEAN__VOID,
276                   G_TYPE_BOOLEAN, 0);
277   /**
278    * GtkIMContext::delete-surrounding:
279    * @context: the object on which the signal is emitted
280    * @offset:  the character offset from the cursor position of the text
281    *           to be deleted. A negative value indicates a position before
282    *           the cursor.
283    * @n_chars: the number of characters to be deleted
284    *
285    * The ::delete-surrounding signal is emitted when the input method
286    * needs to delete all or part of the context surrounding the cursor.
287    *
288    * Return value: %TRUE if the signal was handled.
289    */
290   im_context_signals[DELETE_SURROUNDING] =
291     g_signal_new (I_("delete-surrounding"),
292                   G_TYPE_FROM_CLASS (klass),
293                   G_SIGNAL_RUN_LAST,
294                   G_STRUCT_OFFSET (GtkIMContextClass, delete_surrounding),
295                   _gtk_boolean_handled_accumulator, NULL,
296                   _gtk_marshal_BOOLEAN__INT_INT,
297                   G_TYPE_BOOLEAN, 2,
298                   G_TYPE_INT,
299                   G_TYPE_INT);
300 }
301
302 static void
303 gtk_im_context_init (GtkIMContext *im_context)
304 {
305 }
306
307 static void
308 gtk_im_context_real_get_preedit_string (GtkIMContext       *context,
309                                         gchar             **str,
310                                         PangoAttrList     **attrs,
311                                         gint               *cursor_pos)
312 {
313   if (str)
314     *str = g_strdup ("");
315   if (attrs)
316     *attrs = pango_attr_list_new ();
317   if (cursor_pos)
318     *cursor_pos = 0;
319 }
320
321 static gboolean
322 gtk_im_context_real_filter_keypress (GtkIMContext       *context,
323                                      GdkEventKey        *event)
324 {
325   return FALSE;
326 }
327
328 typedef struct
329 {
330   gchar *text;
331   gint cursor_index;
332 } SurroundingInfo;
333
334 static void
335 gtk_im_context_real_set_surrounding (GtkIMContext  *context,
336                                      const gchar   *text,
337                                      gint           len,
338                                      gint           cursor_index)
339 {
340   SurroundingInfo *info = g_object_get_data (G_OBJECT (context),
341                                              "gtk-im-surrounding-info");
342
343   if (info)
344     {
345       g_free (info->text);
346       info->text = g_strndup (text, len);
347       info->cursor_index = cursor_index;
348     }
349 }
350
351 static gboolean
352 gtk_im_context_real_get_surrounding (GtkIMContext *context,
353                                      gchar       **text,
354                                      gint         *cursor_index)
355 {
356   gboolean result;
357   gboolean info_is_local = FALSE;
358   SurroundingInfo local_info = { NULL, 0 };
359   SurroundingInfo *info;
360   
361   info = g_object_get_data (G_OBJECT (context), "gtk-im-surrounding-info");
362   if (!info)
363     {
364       info = &local_info;
365       g_object_set_data (G_OBJECT (context), I_("gtk-im-surrounding-info"), info);
366       info_is_local = TRUE;
367     }
368   
369   g_signal_emit (context,
370                  im_context_signals[RETRIEVE_SURROUNDING], 0,
371                  &result);
372
373   if (result)
374     {
375       *text = g_strdup (info->text ? info->text : "");
376       *cursor_index = info->cursor_index;
377     }
378   else
379     {
380       *text = NULL;
381       *cursor_index = 0;
382     }
383
384   if (info_is_local)
385     {
386       g_free (info->text);
387       g_object_set_data (G_OBJECT (context), I_("gtk-im-surrounding-info"), NULL);
388     }
389   
390   return result;
391 }
392
393 /**
394  * gtk_im_context_set_client_window:
395  * @context: a #GtkIMContext
396  * @window: (allow-none):  the client window. This may be %NULL to indicate
397  *           that the previous client window no longer exists.
398  * 
399  * Set the client window for the input context; this is the
400  * #GdkWindow in which the input appears. This window is
401  * used in order to correctly position status windows, and may
402  * also be used for purposes internal to the input method.
403  **/
404 void
405 gtk_im_context_set_client_window (GtkIMContext *context,
406                                   GdkWindow    *window)
407 {
408   GtkIMContextClass *klass;
409   
410   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
411
412   klass = GTK_IM_CONTEXT_GET_CLASS (context);
413   if (klass->set_client_window)
414     klass->set_client_window (context, window);
415 }
416
417 /**
418  * gtk_im_context_get_preedit_string:
419  * @context:    a #GtkIMContext
420  * @str:        (out) (transfer full): location to store the retrieved
421  *              string. The string retrieved must be freed with g_free().
422  * @attrs:      (out) (transfer full): location to store the retrieved
423  *              attribute list.  When you are done with this list, you
424  *              must unreference it with pango_attr_list_unref().
425  * @cursor_pos: (out): location to store position of cursor (in characters)
426  *              within the preedit string.  
427  * 
428  * Retrieve the current preedit string for the input context,
429  * and a list of attributes to apply to the string.
430  * This string should be displayed inserted at the insertion
431  * point.
432  **/
433 void
434 gtk_im_context_get_preedit_string (GtkIMContext   *context,
435                                    gchar         **str,
436                                    PangoAttrList **attrs,
437                                    gint           *cursor_pos)
438 {
439   GtkIMContextClass *klass;
440   
441   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
442   
443   klass = GTK_IM_CONTEXT_GET_CLASS (context);
444   klass->get_preedit_string (context, str, attrs, cursor_pos);
445   g_return_if_fail (str == NULL || g_utf8_validate (*str, -1, NULL));
446 }
447
448 /**
449  * gtk_im_context_filter_keypress:
450  * @context: a #GtkIMContext
451  * @event: the key event
452  * 
453  * Allow an input method to internally handle key press and release 
454  * events. If this function returns %TRUE, then no further processing
455  * should be done for this key event.
456  * 
457  * Return value: %TRUE if the input method handled the key event.
458  *
459  **/
460 gboolean
461 gtk_im_context_filter_keypress (GtkIMContext *context,
462                                 GdkEventKey  *key)
463 {
464   GtkIMContextClass *klass;
465   
466   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
467   g_return_val_if_fail (key != NULL, FALSE);
468
469   klass = GTK_IM_CONTEXT_GET_CLASS (context);
470   return klass->filter_keypress (context, key);
471 }
472
473 /**
474  * gtk_im_context_focus_in:
475  * @context: a #GtkIMContext
476  *
477  * Notify the input method that the widget to which this
478  * input context corresponds has gained focus. The input method
479  * may, for example, change the displayed feedback to reflect
480  * this change.
481  **/
482 void
483 gtk_im_context_focus_in (GtkIMContext   *context)
484 {
485   GtkIMContextClass *klass;
486   
487   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
488   
489   klass = GTK_IM_CONTEXT_GET_CLASS (context);
490   if (klass->focus_in)
491     klass->focus_in (context);
492 }
493
494 /**
495  * gtk_im_context_focus_out:
496  * @context: a #GtkIMContext
497  *
498  * Notify the input method that the widget to which this
499  * input context corresponds has lost focus. The input method
500  * may, for example, change the displayed feedback or reset the contexts
501  * state to reflect this change.
502  **/
503 void
504 gtk_im_context_focus_out (GtkIMContext   *context)
505 {
506   GtkIMContextClass *klass;
507   
508   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
509
510   klass = GTK_IM_CONTEXT_GET_CLASS (context);
511   if (klass->focus_out)
512     klass->focus_out (context);
513 }
514
515 /**
516  * gtk_im_context_reset:
517  * @context: a #GtkIMContext
518  *
519  * Notify the input method that a change such as a change in cursor
520  * position has been made. This will typically cause the input
521  * method to clear the preedit state.
522  **/
523 void
524 gtk_im_context_reset (GtkIMContext   *context)
525 {
526   GtkIMContextClass *klass;
527   
528   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
529
530   klass = GTK_IM_CONTEXT_GET_CLASS (context);
531   if (klass->reset)
532     klass->reset (context);
533 }
534
535
536 /**
537  * gtk_im_context_set_cursor_location:
538  * @context: a #GtkIMContext
539  * @area: new location
540  *
541  * Notify the input method that a change in cursor 
542  * position has been made. The location is relative to the client
543  * window.
544  **/
545 void
546 gtk_im_context_set_cursor_location (GtkIMContext       *context,
547                                     const GdkRectangle *area)
548 {
549   GtkIMContextClass *klass;
550   
551   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
552
553   klass = GTK_IM_CONTEXT_GET_CLASS (context);
554   if (klass->set_cursor_location)
555     klass->set_cursor_location (context, (GdkRectangle *) area);
556 }
557
558 /**
559  * gtk_im_context_set_use_preedit:
560  * @context: a #GtkIMContext
561  * @use_preedit: whether the IM context should use the preedit string.
562  * 
563  * Sets whether the IM context should use the preedit string
564  * to display feedback. If @use_preedit is FALSE (default
565  * is TRUE), then the IM context may use some other method to display
566  * feedback, such as displaying it in a child of the root window.
567  **/
568 void
569 gtk_im_context_set_use_preedit (GtkIMContext *context,
570                                 gboolean      use_preedit)
571 {
572   GtkIMContextClass *klass;
573   
574   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
575
576   klass = GTK_IM_CONTEXT_GET_CLASS (context);
577   if (klass->set_use_preedit)
578     klass->set_use_preedit (context, use_preedit);
579 }
580
581 /**
582  * gtk_im_context_set_surrounding:
583  * @context: a #GtkIMContext 
584  * @text: text surrounding the insertion point, as UTF-8.
585  *        the preedit string should not be included within
586  *        @text.
587  * @len: the length of @text, or -1 if @text is nul-terminated
588  * @cursor_index: the byte index of the insertion cursor within @text.
589  * 
590  * Sets surrounding context around the insertion point and preedit
591  * string. This function is expected to be called in response to the
592  * GtkIMContext::retrieve_surrounding signal, and will likely have no
593  * effect if called at other times.
594  **/
595 void
596 gtk_im_context_set_surrounding (GtkIMContext  *context,
597                                 const gchar   *text,
598                                 gint           len,
599                                 gint           cursor_index)
600 {
601   GtkIMContextClass *klass;
602   
603   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
604   g_return_if_fail (text != NULL || len == 0);
605
606   if (text == NULL && len == 0)
607     text = "";
608   if (len < 0)
609     len = strlen (text);
610
611   g_return_if_fail (cursor_index >= 0 && cursor_index <= len);
612
613   klass = GTK_IM_CONTEXT_GET_CLASS (context);
614   if (klass->set_surrounding)
615     klass->set_surrounding (context, text, len, cursor_index);
616 }
617
618 /**
619  * gtk_im_context_get_surrounding:
620  * @context: a #GtkIMContext
621  * @text: (out) (transfer full): location to store a UTF-8 encoded
622  *        string of text holding context around the insertion point.
623  *        If the function returns %TRUE, then you must free the result
624  *        stored in this location with g_free().
625  * @cursor_index: (out) location to store byte index of the insertion
626  *        cursor within @text.
627  * 
628  * Retrieves context around the insertion point. Input methods
629  * typically want context in order to constrain input text based on
630  * existing text; this is important for languages such as Thai where
631  * only some sequences of characters are allowed.
632  *
633  * This function is implemented by emitting the
634  * GtkIMContext::retrieve_surrounding signal on the input method; in
635  * response to this signal, a widget should provide as much context as
636  * is available, up to an entire paragraph, by calling
637  * gtk_im_context_set_surrounding(). Note that there is no obligation
638  * for a widget to respond to the ::retrieve_surrounding signal, so input
639  * methods must be prepared to function without context.
640  *
641  * Return value: %TRUE if surrounding text was provided; in this case
642  *    you must free the result stored in *text.
643  **/
644 gboolean
645 gtk_im_context_get_surrounding (GtkIMContext *context,
646                                 gchar       **text,
647                                 gint         *cursor_index)
648 {
649   GtkIMContextClass *klass;
650   gchar *local_text = NULL;
651   gint local_index;
652   gboolean result = FALSE;
653   
654   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
655
656   klass = GTK_IM_CONTEXT_GET_CLASS (context);
657   if (klass->get_surrounding)
658     result = klass->get_surrounding (context,
659                                      text ? text : &local_text,
660                                      cursor_index ? cursor_index : &local_index);
661
662   if (result)
663     g_free (local_text);
664
665   return result;
666 }
667
668 /**
669  * gtk_im_context_delete_surrounding:
670  * @context: a #GtkIMContext
671  * @offset: offset from cursor position in chars;
672  *    a negative value means start before the cursor.
673  * @n_chars: number of characters to delete.
674  * 
675  * Asks the widget that the input context is attached to to delete
676  * characters around the cursor position by emitting the
677  * GtkIMContext::delete_surrounding signal. Note that @offset and @n_chars
678  * are in characters not in bytes which differs from the usage other
679  * places in #GtkIMContext.
680  *
681  * In order to use this function, you should first call
682  * gtk_im_context_get_surrounding() to get the current context, and
683  * call this function immediately afterwards to make sure that you
684  * know what you are deleting. You should also account for the fact
685  * that even if the signal was handled, the input context might not
686  * have deleted all the characters that were requested to be deleted.
687  *
688  * This function is used by an input method that wants to make
689  * subsitutions in the existing text in response to new input. It is
690  * not useful for applications.
691  * 
692  * Return value: %TRUE if the signal was handled.
693  **/
694 gboolean
695 gtk_im_context_delete_surrounding (GtkIMContext *context,
696                                    gint          offset,
697                                    gint          n_chars)
698 {
699   gboolean result;
700   
701   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
702
703   g_signal_emit (context,
704                  im_context_signals[DELETE_SURROUNDING], 0,
705                  offset, n_chars, &result);
706
707   return result;
708 }