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 {}