Skip to main content

gtk/
text_buffer.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::TextChildAnchor;
4use crate::TextIter;
5use crate::TextTag;
6use crate::{TextBuffer, ffi};
7use glib::object::{Cast, IsA};
8use glib::signal::{SignalHandlerId, connect_raw};
9use glib::translate::*;
10use libc::{c_char, c_int};
11use std::boxed::Box as Box_;
12use std::mem::transmute;
13use std::{slice, str};
14
15pub trait TextBufferExtManual: IsA<TextBuffer> + 'static {
16    /// The ::apply-tag signal is emitted to apply a tag to a
17    /// range of text in a [`TextBuffer`][crate::TextBuffer].
18    /// Applying actually occurs in the default handler.
19    ///
20    /// Note that if your handler runs before the default handler it must not
21    /// invalidate the `start` and `end` iters (or has to revalidate them).
22    ///
23    /// See also:
24    /// [`TextBufferExt::apply_tag()`][crate::prelude::TextBufferExt::apply_tag()],
25    /// `gtk_text_buffer_insert_with_tags()`,
26    /// [`TextBufferExt::insert_range()`][crate::prelude::TextBufferExt::insert_range()].
27    /// ## `tag`
28    /// the applied tag
29    /// ## `start`
30    /// the start of the range the tag is applied to
31    /// ## `end`
32    /// the end of the range the tag is applied to
33    fn connect_apply_tag<F: Fn(&Self, &TextTag, &mut TextIter, &mut TextIter) + 'static>(
34        &self,
35        f: F,
36    ) -> SignalHandlerId {
37        unsafe extern "C" fn apply_tag_trampoline<
38            P,
39            F: Fn(&P, &TextTag, &mut TextIter, &mut TextIter) + 'static,
40        >(
41            this: *mut ffi::GtkTextBuffer,
42            tag: *mut ffi::GtkTextTag,
43            start: *mut ffi::GtkTextIter,
44            end: *mut ffi::GtkTextIter,
45            f: glib::ffi::gpointer,
46        ) where
47            P: IsA<TextBuffer>,
48        {
49            unsafe {
50                let f: &F = &*(f as *const F);
51                let mut start_copy = from_glib_none(start);
52                let mut end_copy = from_glib_none(end);
53
54                f(
55                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
56                    &from_glib_borrow(tag),
57                    &mut start_copy,
58                    &mut end_copy,
59                );
60
61                *start = *start_copy.to_glib_none().0;
62                *end = *end_copy.to_glib_none().0;
63            }
64        }
65        unsafe {
66            let f: Box_<F> = Box_::new(f);
67            connect_raw(
68                self.as_ptr() as *mut _,
69                c"apply-tag".as_ptr() as *const _,
70                Some(transmute::<*const (), unsafe extern "C" fn()>(
71                    apply_tag_trampoline::<Self, F> as *const (),
72                )),
73                Box_::into_raw(f),
74            )
75        }
76    }
77
78    /// The ::delete-range signal is emitted to delete a range
79    /// from a [`TextBuffer`][crate::TextBuffer].
80    ///
81    /// Note that if your handler runs before the default handler it must not
82    /// invalidate the `start` and `end` iters (or has to revalidate them).
83    /// The default signal handler revalidates the `start` and `end` iters to
84    /// both point to the location where text was deleted. Handlers
85    /// which run after the default handler (see `g_signal_connect_after()`)
86    /// do not have access to the deleted text.
87    ///
88    /// See also: [`TextBufferExt::delete()`][crate::prelude::TextBufferExt::delete()].
89    /// ## `start`
90    /// the start of the range to be deleted
91    /// ## `end`
92    /// the end of the range to be deleted
93    fn connect_delete_range<F: Fn(&Self, &mut TextIter, &mut TextIter) + 'static>(
94        &self,
95        f: F,
96    ) -> SignalHandlerId {
97        unsafe extern "C" fn delete_range_trampoline<
98            P,
99            F: Fn(&P, &mut TextIter, &mut TextIter) + 'static,
100        >(
101            this: *mut ffi::GtkTextBuffer,
102            start: *mut ffi::GtkTextIter,
103            end: *mut ffi::GtkTextIter,
104            f: glib::ffi::gpointer,
105        ) where
106            P: IsA<TextBuffer>,
107        {
108            unsafe {
109                let f: &F = &*(f as *const F);
110                let mut start_copy = from_glib_none(start);
111                let mut end_copy = from_glib_none(end);
112
113                f(
114                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
115                    &mut start_copy,
116                    &mut end_copy,
117                );
118
119                *start = *start_copy.to_glib_none().0;
120                *end = *end_copy.to_glib_none().0;
121            }
122        }
123        unsafe {
124            let f: Box_<F> = Box_::new(f);
125            connect_raw(
126                self.as_ptr() as *mut _,
127                c"delete-range".as_ptr() as *const _,
128                Some(transmute::<*const (), unsafe extern "C" fn()>(
129                    delete_range_trampoline::<Self, F> as *const (),
130                )),
131                Box_::into_raw(f),
132            )
133        }
134    }
135
136    /// The ::insert-child-anchor signal is emitted to insert a
137    /// [`TextChildAnchor`][crate::TextChildAnchor] in a [`TextBuffer`][crate::TextBuffer].
138    /// Insertion actually occurs in the default handler.
139    ///
140    /// Note that if your handler runs before the default handler it must
141    /// not invalidate the `location` iter (or has to revalidate it).
142    /// The default signal handler revalidates it to be placed after the
143    /// inserted `anchor`.
144    ///
145    /// See also: [`TextBufferExt::insert_child_anchor()`][crate::prelude::TextBufferExt::insert_child_anchor()].
146    /// ## `location`
147    /// position to insert `anchor` in `textbuffer`
148    /// ## `anchor`
149    /// the [`TextChildAnchor`][crate::TextChildAnchor] to be inserted
150    fn connect_insert_child_anchor<F: Fn(&Self, &mut TextIter, &TextChildAnchor) + 'static>(
151        &self,
152        f: F,
153    ) -> SignalHandlerId {
154        unsafe extern "C" fn insert_child_anchor_trampoline<
155            P,
156            F: Fn(&P, &mut TextIter, &TextChildAnchor) + 'static,
157        >(
158            this: *mut ffi::GtkTextBuffer,
159            location: *mut ffi::GtkTextIter,
160            anchor: *mut ffi::GtkTextChildAnchor,
161            f: glib::ffi::gpointer,
162        ) where
163            P: IsA<TextBuffer>,
164        {
165            unsafe {
166                let f: &F = &*(f as *const F);
167                let mut location_copy = from_glib_none(location);
168
169                f(
170                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
171                    &mut location_copy,
172                    &from_glib_borrow(anchor),
173                );
174
175                *location = *location_copy.to_glib_none().0;
176            }
177        }
178        unsafe {
179            let f: Box_<F> = Box_::new(f);
180            connect_raw(
181                self.as_ptr() as *mut _,
182                c"insert-child-anchor".as_ptr() as *const _,
183                Some(transmute::<*const (), unsafe extern "C" fn()>(
184                    insert_child_anchor_trampoline::<Self, F> as *const (),
185                )),
186                Box_::into_raw(f),
187            )
188        }
189    }
190
191    /// The ::insert-pixbuf signal is emitted to insert a [`gdk_pixbuf::Pixbuf`][crate::gdk_pixbuf::Pixbuf]
192    /// in a [`TextBuffer`][crate::TextBuffer]. Insertion actually occurs in the default handler.
193    ///
194    /// Note that if your handler runs before the default handler it must not
195    /// invalidate the `location` iter (or has to revalidate it).
196    /// The default signal handler revalidates it to be placed after the
197    /// inserted `pixbuf`.
198    ///
199    /// See also: [`TextBufferExt::insert_pixbuf()`][crate::prelude::TextBufferExt::insert_pixbuf()].
200    /// ## `location`
201    /// position to insert `pixbuf` in `textbuffer`
202    /// ## `pixbuf`
203    /// the [`gdk_pixbuf::Pixbuf`][crate::gdk_pixbuf::Pixbuf] to be inserted
204    fn connect_insert_pixbuf<F: Fn(&Self, &mut TextIter, &gdk_pixbuf::Pixbuf) + 'static>(
205        &self,
206        f: F,
207    ) -> SignalHandlerId {
208        unsafe extern "C" fn insert_pixbuf_trampoline<
209            P,
210            F: Fn(&P, &mut TextIter, &gdk_pixbuf::Pixbuf) + 'static,
211        >(
212            this: *mut ffi::GtkTextBuffer,
213            location: *mut ffi::GtkTextIter,
214            pixbuf: *mut gdk_pixbuf::ffi::GdkPixbuf,
215            f: glib::ffi::gpointer,
216        ) where
217            P: IsA<TextBuffer>,
218        {
219            unsafe {
220                let f: &F = &*(f as *const F);
221                let mut location_copy = from_glib_none(location);
222
223                f(
224                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
225                    &mut location_copy,
226                    &from_glib_borrow(pixbuf),
227                );
228
229                *location = *location_copy.to_glib_none().0;
230            }
231        }
232        unsafe {
233            let f: Box_<F> = Box_::new(f);
234            connect_raw(
235                self.as_ptr() as *mut _,
236                c"insert-pixbuf".as_ptr() as *const _,
237                Some(transmute::<*const (), unsafe extern "C" fn()>(
238                    insert_pixbuf_trampoline::<Self, F> as *const (),
239                )),
240                Box_::into_raw(f),
241            )
242        }
243    }
244
245    /// The ::insert-text signal is emitted to insert text in a [`TextBuffer`][crate::TextBuffer].
246    /// Insertion actually occurs in the default handler.
247    ///
248    /// Note that if your handler runs before the default handler it must not
249    /// invalidate the `location` iter (or has to revalidate it).
250    /// The default signal handler revalidates it to point to the end of the
251    /// inserted text.
252    ///
253    /// See also:
254    /// [`TextBufferExt::insert()`][crate::prelude::TextBufferExt::insert()],
255    /// [`TextBufferExt::insert_range()`][crate::prelude::TextBufferExt::insert_range()].
256    /// ## `location`
257    /// position to insert `text` in `textbuffer`
258    /// ## `text`
259    /// the UTF-8 text to be inserted
260    /// ## `len`
261    /// length of the inserted text in bytes
262    fn connect_insert_text<F: Fn(&Self, &mut TextIter, &str) + 'static>(
263        &self,
264        f: F,
265    ) -> SignalHandlerId {
266        unsafe extern "C" fn insert_text_trampoline<T, F: Fn(&T, &mut TextIter, &str) + 'static>(
267            this: *mut ffi::GtkTextBuffer,
268            location: *mut ffi::GtkTextIter,
269            text: *mut c_char,
270            len: c_int,
271            f: glib::ffi::gpointer,
272        ) where
273            T: IsA<TextBuffer>,
274        {
275            unsafe {
276                let f: &F = &*(f as *const F);
277                let mut location_copy = from_glib_none(location);
278
279                let text = if len <= 0 {
280                    &[]
281                } else {
282                    slice::from_raw_parts(text as *const u8, len as usize)
283                };
284
285                f(
286                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
287                    &mut location_copy,
288                    str::from_utf8(text).unwrap(),
289                );
290
291                *location = *location_copy.to_glib_none().0;
292            }
293        }
294        unsafe {
295            let f: Box_<F> = Box_::new(f);
296            connect_raw(
297                self.to_glib_none().0 as *mut _,
298                c"insert-text".as_ptr() as *mut _,
299                Some(transmute::<*const (), unsafe extern "C" fn()>(
300                    insert_text_trampoline::<Self, F> as *const (),
301                )),
302                Box_::into_raw(f),
303            )
304        }
305    }
306
307    /// The ::remove-tag signal is emitted to remove all occurrences of `tag` from
308    /// a range of text in a [`TextBuffer`][crate::TextBuffer].
309    /// Removal actually occurs in the default handler.
310    ///
311    /// Note that if your handler runs before the default handler it must not
312    /// invalidate the `start` and `end` iters (or has to revalidate them).
313    ///
314    /// See also:
315    /// [`TextBufferExt::remove_tag()`][crate::prelude::TextBufferExt::remove_tag()].
316    /// ## `tag`
317    /// the tag to be removed
318    /// ## `start`
319    /// the start of the range the tag is removed from
320    /// ## `end`
321    /// the end of the range the tag is removed from
322    fn connect_remove_tag<F: Fn(&Self, &TextTag, &mut TextIter, &mut TextIter) + 'static>(
323        &self,
324        f: F,
325    ) -> SignalHandlerId {
326        unsafe extern "C" fn remove_tag_trampoline<
327            P,
328            F: Fn(&P, &TextTag, &mut TextIter, &mut TextIter) + 'static,
329        >(
330            this: *mut ffi::GtkTextBuffer,
331            tag: *mut ffi::GtkTextTag,
332            start: *mut ffi::GtkTextIter,
333            end: *mut ffi::GtkTextIter,
334            f: glib::ffi::gpointer,
335        ) where
336            P: IsA<TextBuffer>,
337        {
338            unsafe {
339                let f: &F = &*(f as *const F);
340                let mut start_copy = from_glib_none(start);
341                let mut end_copy = from_glib_none(end);
342
343                f(
344                    TextBuffer::from_glib_borrow(this).unsafe_cast_ref(),
345                    &from_glib_borrow(tag),
346                    &mut start_copy,
347                    &mut end_copy,
348                );
349
350                *start = *start_copy.to_glib_none().0;
351                *end = *end_copy.to_glib_none().0;
352            }
353        }
354        unsafe {
355            let f: Box_<F> = Box_::new(f);
356            connect_raw(
357                self.as_ptr() as *mut _,
358                c"remove-tag".as_ptr() as *const _,
359                Some(transmute::<*const (), unsafe extern "C" fn()>(
360                    remove_tag_trampoline::<Self, F> as *const (),
361                )),
362                Box_::into_raw(f),
363            )
364        }
365    }
366}
367
368impl<O: IsA<TextBuffer>> TextBufferExtManual for O {}