1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gsv.SourceView;
26 
27 private import gdk.Event;
28 private import glib.ConstructionException;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gsv.SourceBuffer;
33 private import gsv.SourceCompletion;
34 private import gsv.SourceGutter;
35 private import gsv.SourceMarkAttributes;
36 private import gsvc.gsv;
37 public  import gsvc.gsvtypes;
38 private import gtk.BuildableIF;
39 private import gtk.BuildableT;
40 private import gtk.ScrollableIF;
41 private import gtk.ScrollableT;
42 private import gtk.TextIter;
43 private import gtk.TextView;
44 private import gtk.Widget;
45 public  import gtkc.gdktypes;
46 private import std.algorithm;
47 
48 
49 /** */
50 public class SourceView : TextView
51 {
52 	/** the main Gtk struct */
53 	protected GtkSourceView* gtkSourceView;
54 
55 	/** Get the main Gtk struct */
56 	public GtkSourceView* getSourceViewStruct()
57 	{
58 		return gtkSourceView;
59 	}
60 
61 	/** the main Gtk struct as a void* */
62 	protected override void* getStruct()
63 	{
64 		return cast(void*)gtkSourceView;
65 	}
66 
67 	protected override void setStruct(GObject* obj)
68 	{
69 		gtkSourceView = cast(GtkSourceView*)obj;
70 		super.setStruct(obj);
71 	}
72 
73 	/**
74 	 * Sets our main struct and passes it to the parent class.
75 	 */
76 	public this (GtkSourceView* gtkSourceView, bool ownedRef = false)
77 	{
78 		this.gtkSourceView = gtkSourceView;
79 		super(cast(GtkTextView*)gtkSourceView, ownedRef);
80 	}
81 
82 	/**
83 	 * Returns the GtkSourceBuffer being displayed by this source view.
84 	 * The reference count on the buffer is not incremented; the caller
85 	 * of this function won't own a new reference.
86 	 *
87 	 * Returns:
88 	 *  a GtkSourceBuffer
89 	 */
90 	public override SourceBuffer getBuffer()
91 	{
92 		auto p = gtk_text_view_get_buffer(cast(GtkTextView*)gtkSourceView);
93 		
94 		return ObjectG.getDObject!(SourceBuffer)(cast(GtkSourceBuffer*) p);
95 	}
96 
97 	/**
98 	 */
99 
100 	/** */
101 	public static GType getType()
102 	{
103 		return gtk_source_view_get_type();
104 	}
105 
106 	/**
107 	 * Creates a new #GtkSourceView.
108 	 *
109 	 * By default, an empty #GtkSourceBuffer will be lazily created and can be
110 	 * retrieved with gtk_text_view_get_buffer().
111 	 *
112 	 * If you want to specify your own buffer, either override the
113 	 * #GtkTextViewClass create_buffer factory method, or use
114 	 * gtk_source_view_new_with_buffer().
115 	 *
116 	 * Return: a new #GtkSourceView.
117 	 *
118 	 * Throws: ConstructionException GTK+ fails to create the object.
119 	 */
120 	public this()
121 	{
122 		auto p = gtk_source_view_new();
123 		
124 		if(p is null)
125 		{
126 			throw new ConstructionException("null returned by new");
127 		}
128 		
129 		this(cast(GtkSourceView*) p);
130 	}
131 
132 	/**
133 	 * Creates a new #GtkSourceView widget displaying the buffer
134 	 * @buffer. One buffer can be shared among many widgets.
135 	 *
136 	 * Params:
137 	 *     buffer = a #GtkSourceBuffer.
138 	 *
139 	 * Return: a new #GtkSourceView.
140 	 *
141 	 * Throws: ConstructionException GTK+ fails to create the object.
142 	 */
143 	public this(SourceBuffer buffer)
144 	{
145 		auto p = gtk_source_view_new_with_buffer((buffer is null) ? null : buffer.getSourceBufferStruct());
146 		
147 		if(p is null)
148 		{
149 			throw new ConstructionException("null returned by new_with_buffer");
150 		}
151 		
152 		this(cast(GtkSourceView*) p);
153 	}
154 
155 	/**
156 	 * Returns whether auto-indentation of text is enabled.
157 	 *
158 	 * Return: %TRUE if auto indentation is enabled.
159 	 */
160 	public bool getAutoIndent()
161 	{
162 		return gtk_source_view_get_auto_indent(gtkSourceView) != 0;
163 	}
164 
165 	/**
166 	 * Returns the #GtkSourceBackgroundPatternType specifying if and how
167 	 * the background pattern should be displayed for this @view.
168 	 *
169 	 * Return: the #GtkSourceBackgroundPatternType.
170 	 *
171 	 * Since: 3.16
172 	 */
173 	public GtkSourceBackgroundPatternType getBackgroundPattern()
174 	{
175 		return gtk_source_view_get_background_pattern(gtkSourceView);
176 	}
177 
178 	/**
179 	 * Gets the #GtkSourceCompletion associated with @view.
180 	 *
181 	 * Return: the #GtkSourceCompletion associated with @view.
182 	 */
183 	public SourceCompletion getCompletion()
184 	{
185 		auto p = gtk_source_view_get_completion(gtkSourceView);
186 		
187 		if(p is null)
188 		{
189 			return null;
190 		}
191 		
192 		return ObjectG.getDObject!(SourceCompletion)(cast(GtkSourceCompletion*) p);
193 	}
194 
195 	/**
196 	 * Returns the #GtkSourceDrawSpacesFlags specifying if and how spaces
197 	 * should be displayed for this @view.
198 	 *
199 	 * Return: the #GtkSourceDrawSpacesFlags, 0 if no spaces should be drawn.
200 	 */
201 	public GtkSourceDrawSpacesFlags getDrawSpaces()
202 	{
203 		return gtk_source_view_get_draw_spaces(gtkSourceView);
204 	}
205 
206 	/**
207 	 * Returns the #GtkSourceGutter object associated with @window_type for @view.
208 	 * Only GTK_TEXT_WINDOW_LEFT and GTK_TEXT_WINDOW_RIGHT are supported,
209 	 * respectively corresponding to the left and right gutter. The line numbers
210 	 * and mark category icons are rendered in the left gutter.
211 	 *
212 	 * Params:
213 	 *     windowType = the gutter window type.
214 	 *
215 	 * Return: the #GtkSourceGutter.
216 	 *
217 	 * Since: 2.8
218 	 */
219 	public SourceGutter getGutter(GtkTextWindowType windowType)
220 	{
221 		auto p = gtk_source_view_get_gutter(gtkSourceView, windowType);
222 		
223 		if(p is null)
224 		{
225 			return null;
226 		}
227 		
228 		return ObjectG.getDObject!(SourceGutter)(cast(GtkSourceGutter*) p);
229 	}
230 
231 	/**
232 	 * Returns whether the current line is highlighted.
233 	 *
234 	 * Return: %TRUE if the current line is highlighted.
235 	 */
236 	public bool getHighlightCurrentLine()
237 	{
238 		return gtk_source_view_get_highlight_current_line(gtkSourceView) != 0;
239 	}
240 
241 	/**
242 	 * Returns whether when the tab key is pressed the current selection
243 	 * should get indented instead of replaced with the \t character.
244 	 *
245 	 * Return: %TRUE if the selection is indented when tab is pressed.
246 	 */
247 	public bool getIndentOnTab()
248 	{
249 		return gtk_source_view_get_indent_on_tab(gtkSourceView) != 0;
250 	}
251 
252 	/**
253 	 * Returns the number of spaces to use for each step of indent.
254 	 * See gtk_source_view_set_indent_width() for details.
255 	 *
256 	 * Return: indent width.
257 	 */
258 	public int getIndentWidth()
259 	{
260 		return gtk_source_view_get_indent_width(gtkSourceView);
261 	}
262 
263 	/**
264 	 * Returns whether when inserting a tabulator character it should
265 	 * be replaced by a group of space characters.
266 	 *
267 	 * Return: %TRUE if spaces are inserted instead of tabs.
268 	 */
269 	public bool getInsertSpacesInsteadOfTabs()
270 	{
271 		return gtk_source_view_get_insert_spaces_instead_of_tabs(gtkSourceView) != 0;
272 	}
273 
274 	/**
275 	 * Gets attributes and priority for the @category.
276 	 *
277 	 * Params:
278 	 *     category = the category.
279 	 *     priority = place where priority of the category will be stored.
280 	 *
281 	 * Return: #GtkSourceMarkAttributes for the @category.
282 	 *     The object belongs to @view, so it must not be unreffed.
283 	 */
284 	public SourceMarkAttributes getMarkAttributes(string category, int* priority)
285 	{
286 		auto p = gtk_source_view_get_mark_attributes(gtkSourceView, Str.toStringz(category), priority);
287 		
288 		if(p is null)
289 		{
290 			return null;
291 		}
292 		
293 		return ObjectG.getDObject!(SourceMarkAttributes)(cast(GtkSourceMarkAttributes*) p);
294 	}
295 
296 	/**
297 	 * Gets the position of the right margin in the given @view.
298 	 *
299 	 * Return: the position of the right margin.
300 	 */
301 	public uint getRightMarginPosition()
302 	{
303 		return gtk_source_view_get_right_margin_position(gtkSourceView);
304 	}
305 
306 	/**
307 	 * Returns whether line marks are displayed beside the text.
308 	 *
309 	 * Return: %TRUE if the line marks are displayed.
310 	 *
311 	 * Since: 2.2
312 	 */
313 	public bool getShowLineMarks()
314 	{
315 		return gtk_source_view_get_show_line_marks(gtkSourceView) != 0;
316 	}
317 
318 	/**
319 	 * Returns whether line numbers are displayed beside the text.
320 	 *
321 	 * Return: %TRUE if the line numbers are displayed.
322 	 */
323 	public bool getShowLineNumbers()
324 	{
325 		return gtk_source_view_get_show_line_numbers(gtkSourceView) != 0;
326 	}
327 
328 	/**
329 	 * Returns whether a right margin is displayed.
330 	 *
331 	 * Return: %TRUE if the right margin is shown.
332 	 */
333 	public bool getShowRightMargin()
334 	{
335 		return gtk_source_view_get_show_right_margin(gtkSourceView) != 0;
336 	}
337 
338 	/**
339 	 * Returns %TRUE if pressing the Backspace key will try to delete spaces
340 	 * up to the previous tab stop.
341 	 *
342 	 * Return: %TRUE if smart Backspace handling is enabled.
343 	 *
344 	 * Since: 3.18
345 	 */
346 	public bool getSmartBackspace()
347 	{
348 		return gtk_source_view_get_smart_backspace(gtkSourceView) != 0;
349 	}
350 
351 	/**
352 	 * Returns a #GtkSourceSmartHomeEndType end value specifying
353 	 * how the cursor will move when HOME and END keys are pressed.
354 	 *
355 	 * Return: a #GtkSourceSmartHomeEndType value.
356 	 */
357 	public GtkSourceSmartHomeEndType getSmartHomeEnd()
358 	{
359 		return gtk_source_view_get_smart_home_end(gtkSourceView);
360 	}
361 
362 	/**
363 	 * Returns the width of tabulation in characters.
364 	 *
365 	 * Return: width of tab.
366 	 */
367 	public uint getTabWidth()
368 	{
369 		return gtk_source_view_get_tab_width(gtkSourceView);
370 	}
371 
372 	/**
373 	 * Determines the visual column at @iter taking into consideration the
374 	 * #GtkSourceView:tab-width of @view.
375 	 *
376 	 * Params:
377 	 *     iter = a position in @view.
378 	 *
379 	 * Return: the visual column at @iter.
380 	 */
381 	public uint getVisualColumn(TextIter iter)
382 	{
383 		return gtk_source_view_get_visual_column(gtkSourceView, (iter is null) ? null : iter.getTextIterStruct());
384 	}
385 
386 	/**
387 	 * Insert one indentation level at the beginning of the
388 	 * specified lines.
389 	 *
390 	 * Params:
391 	 *     start = #GtkTextIter of the first line to indent
392 	 *     end = #GtkTextIter of the last line to indent
393 	 *
394 	 * Since: 3.16
395 	 */
396 	public void indentLines(TextIter start, TextIter end)
397 	{
398 		gtk_source_view_indent_lines(gtkSourceView, (start is null) ? null : start.getTextIterStruct(), (end is null) ? null : end.getTextIterStruct());
399 	}
400 
401 	/**
402 	 * If %TRUE auto-indentation of text is enabled.
403 	 *
404 	 * When Enter is pressed to create a new line, the auto-indentation inserts the
405 	 * same indentation as the previous line. This is <emphasis>not</emphasis> a
406 	 * "smart indentation" where an indentation level is added or removed depending
407 	 * on the context.
408 	 *
409 	 * Params:
410 	 *     enable = whether to enable auto indentation.
411 	 */
412 	public void setAutoIndent(bool enable)
413 	{
414 		gtk_source_view_set_auto_indent(gtkSourceView, enable);
415 	}
416 
417 	/**
418 	 * Set if and how the background pattern should be displayed.
419 	 *
420 	 * Params:
421 	 *     backgroundPattern = the #GtkSourceBackgroundPatternType.
422 	 *
423 	 * Since: 3.16
424 	 */
425 	public void setBackgroundPattern(GtkSourceBackgroundPatternType backgroundPattern)
426 	{
427 		gtk_source_view_set_background_pattern(gtkSourceView, backgroundPattern);
428 	}
429 
430 	/**
431 	 * Set if and how the spaces should be visualized. Specifying @flags as 0 will
432 	 * disable display of spaces.
433 	 *
434 	 * For a finer-grained method, there is also the GtkSourceTag's
435 	 * #GtkSourceTag:draw-spaces property.
436 	 *
437 	 * Params:
438 	 *     flags = #GtkSourceDrawSpacesFlags specifing how white spaces should
439 	 *         be displayed
440 	 */
441 	public void setDrawSpaces(GtkSourceDrawSpacesFlags flags)
442 	{
443 		gtk_source_view_set_draw_spaces(gtkSourceView, flags);
444 	}
445 
446 	/**
447 	 * If @highlight is %TRUE the current line will be highlighted.
448 	 *
449 	 * Params:
450 	 *     highlight = whether to highlight the current line.
451 	 */
452 	public void setHighlightCurrentLine(bool highlight)
453 	{
454 		gtk_source_view_set_highlight_current_line(gtkSourceView, highlight);
455 	}
456 
457 	/**
458 	 * If %TRUE, when the tab key is pressed when several lines are selected, the
459 	 * selected lines are indented of one level instead of being replaced with a \t
460 	 * character. Shift+Tab unindents the selection.
461 	 *
462 	 * If the first or last line is not selected completely, it is also indented or
463 	 * unindented.
464 	 *
465 	 * When the selection doesn't span several lines, the tab key always replaces
466 	 * the selection with a normal \t character.
467 	 *
468 	 * Params:
469 	 *     enable = whether to indent a block when tab is pressed.
470 	 */
471 	public void setIndentOnTab(bool enable)
472 	{
473 		gtk_source_view_set_indent_on_tab(gtkSourceView, enable);
474 	}
475 
476 	/**
477 	 * Sets the number of spaces to use for each step of indent when the tab key is
478 	 * pressed. If @width is -1, the value of the #GtkSourceView:tab-width property
479 	 * will be used.
480 	 *
481 	 * The #GtkSourceView:indent-width interacts with the
482 	 * #GtkSourceView:insert-spaces-instead-of-tabs property and
483 	 * #GtkSourceView:tab-width. An example will be clearer: if the
484 	 * #GtkSourceView:indent-width is 4 and
485 	 * #GtkSourceView:tab-width is 8 and
486 	 * #GtkSourceView:insert-spaces-instead-of-tabs is %FALSE, then pressing the tab
487 	 * key at the beginning of a line will insert 4 spaces. So far so good. Pressing
488 	 * the tab key a second time will remove the 4 spaces and insert a \t character
489 	 * instead (since #GtkSourceView:tab-width is 8). On the other hand, if
490 	 * #GtkSourceView:insert-spaces-instead-of-tabs is %TRUE, the second tab key
491 	 * pressed will insert 4 more spaces for a total of 8 spaces in the
492 	 * #GtkTextBuffer.
493 	 *
494 	 * The test-widget program (available in the GtkSourceView repository) may be
495 	 * useful to better understand the indentation settings (enable the space
496 	 * drawing!).
497 	 *
498 	 * Params:
499 	 *     width = indent width in characters.
500 	 */
501 	public void setIndentWidth(int width)
502 	{
503 		gtk_source_view_set_indent_width(gtkSourceView, width);
504 	}
505 
506 	/**
507 	 * If %TRUE a tab key pressed is replaced by a group of space characters. Of
508 	 * course it is still possible to insert a real \t programmatically with the
509 	 * #GtkTextBuffer API.
510 	 *
511 	 * Params:
512 	 *     enable = whether to insert spaces instead of tabs.
513 	 */
514 	public void setInsertSpacesInsteadOfTabs(bool enable)
515 	{
516 		gtk_source_view_set_insert_spaces_instead_of_tabs(gtkSourceView, enable);
517 	}
518 
519 	/**
520 	 * Sets attributes and priority for the @category.
521 	 *
522 	 * Params:
523 	 *     category = the category.
524 	 *     attributes = mark attributes.
525 	 *     priority = priority of the category.
526 	 */
527 	public void setMarkAttributes(string category, SourceMarkAttributes attributes, int priority)
528 	{
529 		gtk_source_view_set_mark_attributes(gtkSourceView, Str.toStringz(category), (attributes is null) ? null : attributes.getSourceMarkAttributesStruct(), priority);
530 	}
531 
532 	/**
533 	 * Sets the position of the right margin in the given @view.
534 	 *
535 	 * Params:
536 	 *     pos = the width in characters where to position the right margin.
537 	 */
538 	public void setRightMarginPosition(uint pos)
539 	{
540 		gtk_source_view_set_right_margin_position(gtkSourceView, pos);
541 	}
542 
543 	/**
544 	 * If %TRUE line marks will be displayed beside the text.
545 	 *
546 	 * Params:
547 	 *     show = whether line marks should be displayed.
548 	 *
549 	 * Since: 2.2
550 	 */
551 	public void setShowLineMarks(bool show)
552 	{
553 		gtk_source_view_set_show_line_marks(gtkSourceView, show);
554 	}
555 
556 	/**
557 	 * If %TRUE line numbers will be displayed beside the text.
558 	 *
559 	 * Params:
560 	 *     show = whether line numbers should be displayed.
561 	 */
562 	public void setShowLineNumbers(bool show)
563 	{
564 		gtk_source_view_set_show_line_numbers(gtkSourceView, show);
565 	}
566 
567 	/**
568 	 * If %TRUE a right margin is displayed.
569 	 *
570 	 * Params:
571 	 *     show = whether to show a right margin.
572 	 */
573 	public void setShowRightMargin(bool show)
574 	{
575 		gtk_source_view_set_show_right_margin(gtkSourceView, show);
576 	}
577 
578 	/**
579 	 * When set to %TRUE, pressing the Backspace key will try to delete spaces
580 	 * up to the previous tab stop.
581 	 *
582 	 * Params:
583 	 *     smartBackspace = whether to enable smart Backspace handling.
584 	 *
585 	 * Since: 3.18
586 	 */
587 	public void setSmartBackspace(bool smartBackspace)
588 	{
589 		gtk_source_view_set_smart_backspace(gtkSourceView, smartBackspace);
590 	}
591 
592 	/**
593 	 * Set the desired movement of the cursor when HOME and END keys
594 	 * are pressed.
595 	 *
596 	 * Params:
597 	 *     smartHomeEnd = the desired behavior among #GtkSourceSmartHomeEndType.
598 	 */
599 	public void setSmartHomeEnd(GtkSourceSmartHomeEndType smartHomeEnd)
600 	{
601 		gtk_source_view_set_smart_home_end(gtkSourceView, smartHomeEnd);
602 	}
603 
604 	/**
605 	 * Sets the width of tabulation in characters. The #GtkTextBuffer still contains
606 	 * \t characters, but they can take a different visual width in a #GtkSourceView
607 	 * widget.
608 	 *
609 	 * Params:
610 	 *     width = width of tab in characters.
611 	 */
612 	public void setTabWidth(uint width)
613 	{
614 		gtk_source_view_set_tab_width(gtkSourceView, width);
615 	}
616 
617 	/**
618 	 * Removes one indentation level at the beginning of the
619 	 * specified lines.
620 	 *
621 	 * Params:
622 	 *     start = #GtkTextIter of the first line to indent
623 	 *     end = #GtkTextIter of the last line to indent
624 	 *
625 	 * Since: 3.16
626 	 */
627 	public void unindentLines(TextIter start, TextIter end)
628 	{
629 		gtk_source_view_unindent_lines(gtkSourceView, (start is null) ? null : start.getTextIterStruct(), (end is null) ? null : end.getTextIterStruct());
630 	}
631 
632 	protected class OnChangeCaseDelegateWrapper
633 	{
634 		void delegate(GtkSourceChangeCaseType, SourceView) dlg;
635 		gulong handlerId;
636 		ConnectFlags flags;
637 		this(void delegate(GtkSourceChangeCaseType, SourceView) dlg, gulong handlerId, ConnectFlags flags)
638 		{
639 			this.dlg = dlg;
640 			this.handlerId = handlerId;
641 			this.flags = flags;
642 		}
643 	}
644 	protected OnChangeCaseDelegateWrapper[] onChangeCaseListeners;
645 
646 	/**
647 	 * Keybinding signal to change case of the text at the current cursor position.
648 	 *
649 	 * Params:
650 	 *     caseType = the case to use
651 	 *
652 	 * Since: 3.16
653 	 */
654 	gulong addOnChangeCase(void delegate(GtkSourceChangeCaseType, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
655 	{
656 		onChangeCaseListeners ~= new OnChangeCaseDelegateWrapper(dlg, 0, connectFlags);
657 		onChangeCaseListeners[onChangeCaseListeners.length - 1].handlerId = Signals.connectData(
658 			this,
659 			"change-case",
660 			cast(GCallback)&callBackChangeCase,
661 			cast(void*)onChangeCaseListeners[onChangeCaseListeners.length - 1],
662 			cast(GClosureNotify)&callBackChangeCaseDestroy,
663 			connectFlags);
664 		return onChangeCaseListeners[onChangeCaseListeners.length - 1].handlerId;
665 	}
666 	
667 	extern(C) static void callBackChangeCase(GtkSourceView* sourceviewStruct, GtkSourceChangeCaseType caseType,OnChangeCaseDelegateWrapper wrapper)
668 	{
669 		wrapper.dlg(caseType, wrapper.outer);
670 	}
671 	
672 	extern(C) static void callBackChangeCaseDestroy(OnChangeCaseDelegateWrapper wrapper, GClosure* closure)
673 	{
674 		wrapper.outer.internalRemoveOnChangeCase(wrapper);
675 	}
676 
677 	protected void internalRemoveOnChangeCase(OnChangeCaseDelegateWrapper source)
678 	{
679 		foreach(index, wrapper; onChangeCaseListeners)
680 		{
681 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
682 			{
683 				onChangeCaseListeners[index] = null;
684 				onChangeCaseListeners = std.algorithm.remove(onChangeCaseListeners, index);
685 				break;
686 			}
687 		}
688 	}
689 	
690 
691 	protected class OnChangeNumberDelegateWrapper
692 	{
693 		void delegate(int, SourceView) dlg;
694 		gulong handlerId;
695 		ConnectFlags flags;
696 		this(void delegate(int, SourceView) dlg, gulong handlerId, ConnectFlags flags)
697 		{
698 			this.dlg = dlg;
699 			this.handlerId = handlerId;
700 			this.flags = flags;
701 		}
702 	}
703 	protected OnChangeNumberDelegateWrapper[] onChangeNumberListeners;
704 
705 	/**
706 	 * Keybinding signal to edit a number at the current cursor position.
707 	 *
708 	 * Params:
709 	 *     count = the number to add to the number at the current position
710 	 *
711 	 * Since: 3.16
712 	 */
713 	gulong addOnChangeNumber(void delegate(int, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
714 	{
715 		onChangeNumberListeners ~= new OnChangeNumberDelegateWrapper(dlg, 0, connectFlags);
716 		onChangeNumberListeners[onChangeNumberListeners.length - 1].handlerId = Signals.connectData(
717 			this,
718 			"change-number",
719 			cast(GCallback)&callBackChangeNumber,
720 			cast(void*)onChangeNumberListeners[onChangeNumberListeners.length - 1],
721 			cast(GClosureNotify)&callBackChangeNumberDestroy,
722 			connectFlags);
723 		return onChangeNumberListeners[onChangeNumberListeners.length - 1].handlerId;
724 	}
725 	
726 	extern(C) static void callBackChangeNumber(GtkSourceView* sourceviewStruct, int count,OnChangeNumberDelegateWrapper wrapper)
727 	{
728 		wrapper.dlg(count, wrapper.outer);
729 	}
730 	
731 	extern(C) static void callBackChangeNumberDestroy(OnChangeNumberDelegateWrapper wrapper, GClosure* closure)
732 	{
733 		wrapper.outer.internalRemoveOnChangeNumber(wrapper);
734 	}
735 
736 	protected void internalRemoveOnChangeNumber(OnChangeNumberDelegateWrapper source)
737 	{
738 		foreach(index, wrapper; onChangeNumberListeners)
739 		{
740 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
741 			{
742 				onChangeNumberListeners[index] = null;
743 				onChangeNumberListeners = std.algorithm.remove(onChangeNumberListeners, index);
744 				break;
745 			}
746 		}
747 	}
748 	
749 
750 	protected class OnJoinLinesDelegateWrapper
751 	{
752 		void delegate(SourceView) dlg;
753 		gulong handlerId;
754 		ConnectFlags flags;
755 		this(void delegate(SourceView) dlg, gulong handlerId, ConnectFlags flags)
756 		{
757 			this.dlg = dlg;
758 			this.handlerId = handlerId;
759 			this.flags = flags;
760 		}
761 	}
762 	protected OnJoinLinesDelegateWrapper[] onJoinLinesListeners;
763 
764 	/**
765 	 * Keybinding signal to join the lines currently selected.
766 	 *
767 	 * Since: 3.16
768 	 */
769 	gulong addOnJoinLines(void delegate(SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
770 	{
771 		onJoinLinesListeners ~= new OnJoinLinesDelegateWrapper(dlg, 0, connectFlags);
772 		onJoinLinesListeners[onJoinLinesListeners.length - 1].handlerId = Signals.connectData(
773 			this,
774 			"join-lines",
775 			cast(GCallback)&callBackJoinLines,
776 			cast(void*)onJoinLinesListeners[onJoinLinesListeners.length - 1],
777 			cast(GClosureNotify)&callBackJoinLinesDestroy,
778 			connectFlags);
779 		return onJoinLinesListeners[onJoinLinesListeners.length - 1].handlerId;
780 	}
781 	
782 	extern(C) static void callBackJoinLines(GtkSourceView* sourceviewStruct,OnJoinLinesDelegateWrapper wrapper)
783 	{
784 		wrapper.dlg(wrapper.outer);
785 	}
786 	
787 	extern(C) static void callBackJoinLinesDestroy(OnJoinLinesDelegateWrapper wrapper, GClosure* closure)
788 	{
789 		wrapper.outer.internalRemoveOnJoinLines(wrapper);
790 	}
791 
792 	protected void internalRemoveOnJoinLines(OnJoinLinesDelegateWrapper source)
793 	{
794 		foreach(index, wrapper; onJoinLinesListeners)
795 		{
796 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
797 			{
798 				onJoinLinesListeners[index] = null;
799 				onJoinLinesListeners = std.algorithm.remove(onJoinLinesListeners, index);
800 				break;
801 			}
802 		}
803 	}
804 	
805 
806 	protected class OnLineMarkActivatedDelegateWrapper
807 	{
808 		void delegate(TextIter, Event, SourceView) dlg;
809 		gulong handlerId;
810 		ConnectFlags flags;
811 		this(void delegate(TextIter, Event, SourceView) dlg, gulong handlerId, ConnectFlags flags)
812 		{
813 			this.dlg = dlg;
814 			this.handlerId = handlerId;
815 			this.flags = flags;
816 		}
817 	}
818 	protected OnLineMarkActivatedDelegateWrapper[] onLineMarkActivatedListeners;
819 
820 	/**
821 	 * Emitted when a line mark has been activated (for instance when there
822 	 * was a button press in the line marks gutter). You can use @iter to
823 	 * determine on which line the activation took place.
824 	 *
825 	 * Params:
826 	 *     iter = a #GtkTextIter
827 	 *     event = the #GdkEvent that activated the event
828 	 */
829 	gulong addOnLineMarkActivated(void delegate(TextIter, Event, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
830 	{
831 		onLineMarkActivatedListeners ~= new OnLineMarkActivatedDelegateWrapper(dlg, 0, connectFlags);
832 		onLineMarkActivatedListeners[onLineMarkActivatedListeners.length - 1].handlerId = Signals.connectData(
833 			this,
834 			"line-mark-activated",
835 			cast(GCallback)&callBackLineMarkActivated,
836 			cast(void*)onLineMarkActivatedListeners[onLineMarkActivatedListeners.length - 1],
837 			cast(GClosureNotify)&callBackLineMarkActivatedDestroy,
838 			connectFlags);
839 		return onLineMarkActivatedListeners[onLineMarkActivatedListeners.length - 1].handlerId;
840 	}
841 	
842 	extern(C) static void callBackLineMarkActivated(GtkSourceView* sourceviewStruct, GtkTextIter* iter, GdkEvent* event,OnLineMarkActivatedDelegateWrapper wrapper)
843 	{
844 		wrapper.dlg(ObjectG.getDObject!(TextIter)(iter), ObjectG.getDObject!(Event)(event), wrapper.outer);
845 	}
846 	
847 	extern(C) static void callBackLineMarkActivatedDestroy(OnLineMarkActivatedDelegateWrapper wrapper, GClosure* closure)
848 	{
849 		wrapper.outer.internalRemoveOnLineMarkActivated(wrapper);
850 	}
851 
852 	protected void internalRemoveOnLineMarkActivated(OnLineMarkActivatedDelegateWrapper source)
853 	{
854 		foreach(index, wrapper; onLineMarkActivatedListeners)
855 		{
856 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
857 			{
858 				onLineMarkActivatedListeners[index] = null;
859 				onLineMarkActivatedListeners = std.algorithm.remove(onLineMarkActivatedListeners, index);
860 				break;
861 			}
862 		}
863 	}
864 	
865 
866 	protected class OnMoveLinesDelegateWrapper
867 	{
868 		void delegate(bool, int, SourceView) dlg;
869 		gulong handlerId;
870 		ConnectFlags flags;
871 		this(void delegate(bool, int, SourceView) dlg, gulong handlerId, ConnectFlags flags)
872 		{
873 			this.dlg = dlg;
874 			this.handlerId = handlerId;
875 			this.flags = flags;
876 		}
877 	}
878 	protected OnMoveLinesDelegateWrapper[] onMoveLinesListeners;
879 
880 	/**
881 	 * The ::move-lines signal is a keybinding which gets emitted
882 	 * when the user initiates moving a line. The default binding key
883 	 * is Alt+Up/Down arrow. And moves the currently selected lines,
884 	 * or the current line by @count. For the moment, only
885 	 * @count of -1 or 1 is valid.
886 	 *
887 	 * Params:
888 	 *     copy = %TRUE if the line should be copied,
889 	 *         %FALSE if it should be moved
890 	 *     count = the number of lines to move over.
891 	 *
892 	 * Since: 2.10
893 	 */
894 	gulong addOnMoveLines(void delegate(bool, int, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
895 	{
896 		onMoveLinesListeners ~= new OnMoveLinesDelegateWrapper(dlg, 0, connectFlags);
897 		onMoveLinesListeners[onMoveLinesListeners.length - 1].handlerId = Signals.connectData(
898 			this,
899 			"move-lines",
900 			cast(GCallback)&callBackMoveLines,
901 			cast(void*)onMoveLinesListeners[onMoveLinesListeners.length - 1],
902 			cast(GClosureNotify)&callBackMoveLinesDestroy,
903 			connectFlags);
904 		return onMoveLinesListeners[onMoveLinesListeners.length - 1].handlerId;
905 	}
906 	
907 	extern(C) static void callBackMoveLines(GtkSourceView* sourceviewStruct, bool copy, int count,OnMoveLinesDelegateWrapper wrapper)
908 	{
909 		wrapper.dlg(copy, count, wrapper.outer);
910 	}
911 	
912 	extern(C) static void callBackMoveLinesDestroy(OnMoveLinesDelegateWrapper wrapper, GClosure* closure)
913 	{
914 		wrapper.outer.internalRemoveOnMoveLines(wrapper);
915 	}
916 
917 	protected void internalRemoveOnMoveLines(OnMoveLinesDelegateWrapper source)
918 	{
919 		foreach(index, wrapper; onMoveLinesListeners)
920 		{
921 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
922 			{
923 				onMoveLinesListeners[index] = null;
924 				onMoveLinesListeners = std.algorithm.remove(onMoveLinesListeners, index);
925 				break;
926 			}
927 		}
928 	}
929 	
930 
931 	protected class OnMoveToMatchingBracketDelegateWrapper
932 	{
933 		void delegate(bool, SourceView) dlg;
934 		gulong handlerId;
935 		ConnectFlags flags;
936 		this(void delegate(bool, SourceView) dlg, gulong handlerId, ConnectFlags flags)
937 		{
938 			this.dlg = dlg;
939 			this.handlerId = handlerId;
940 			this.flags = flags;
941 		}
942 	}
943 	protected OnMoveToMatchingBracketDelegateWrapper[] onMoveToMatchingBracketListeners;
944 
945 	/**
946 	 * Keybinding signal to move the cursor to the matching bracket.
947 	 *
948 	 * Params:
949 	 *     extendSelection = %TRUE if the move should extend the selection
950 	 *
951 	 * Since: 3.16
952 	 */
953 	gulong addOnMoveToMatchingBracket(void delegate(bool, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
954 	{
955 		onMoveToMatchingBracketListeners ~= new OnMoveToMatchingBracketDelegateWrapper(dlg, 0, connectFlags);
956 		onMoveToMatchingBracketListeners[onMoveToMatchingBracketListeners.length - 1].handlerId = Signals.connectData(
957 			this,
958 			"move-to-matching-bracket",
959 			cast(GCallback)&callBackMoveToMatchingBracket,
960 			cast(void*)onMoveToMatchingBracketListeners[onMoveToMatchingBracketListeners.length - 1],
961 			cast(GClosureNotify)&callBackMoveToMatchingBracketDestroy,
962 			connectFlags);
963 		return onMoveToMatchingBracketListeners[onMoveToMatchingBracketListeners.length - 1].handlerId;
964 	}
965 	
966 	extern(C) static void callBackMoveToMatchingBracket(GtkSourceView* sourceviewStruct, bool extendSelection,OnMoveToMatchingBracketDelegateWrapper wrapper)
967 	{
968 		wrapper.dlg(extendSelection, wrapper.outer);
969 	}
970 	
971 	extern(C) static void callBackMoveToMatchingBracketDestroy(OnMoveToMatchingBracketDelegateWrapper wrapper, GClosure* closure)
972 	{
973 		wrapper.outer.internalRemoveOnMoveToMatchingBracket(wrapper);
974 	}
975 
976 	protected void internalRemoveOnMoveToMatchingBracket(OnMoveToMatchingBracketDelegateWrapper source)
977 	{
978 		foreach(index, wrapper; onMoveToMatchingBracketListeners)
979 		{
980 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
981 			{
982 				onMoveToMatchingBracketListeners[index] = null;
983 				onMoveToMatchingBracketListeners = std.algorithm.remove(onMoveToMatchingBracketListeners, index);
984 				break;
985 			}
986 		}
987 	}
988 	
989 
990 	protected class OnMoveWordsDelegateWrapper
991 	{
992 		void delegate(int, SourceView) dlg;
993 		gulong handlerId;
994 		ConnectFlags flags;
995 		this(void delegate(int, SourceView) dlg, gulong handlerId, ConnectFlags flags)
996 		{
997 			this.dlg = dlg;
998 			this.handlerId = handlerId;
999 			this.flags = flags;
1000 		}
1001 	}
1002 	protected OnMoveWordsDelegateWrapper[] onMoveWordsListeners;
1003 
1004 	/**
1005 	 * The ::move-words signal is a keybinding which gets emitted
1006 	 * when the user initiates moving a word. The default binding key
1007 	 * is Alt+Left/Right Arrow and moves the current selection, or the current
1008 	 * word by one word.
1009 	 *
1010 	 * Params:
1011 	 *     count = the number of words to move over
1012 	 *
1013 	 * Since: 3.0
1014 	 */
1015 	gulong addOnMoveWords(void delegate(int, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1016 	{
1017 		onMoveWordsListeners ~= new OnMoveWordsDelegateWrapper(dlg, 0, connectFlags);
1018 		onMoveWordsListeners[onMoveWordsListeners.length - 1].handlerId = Signals.connectData(
1019 			this,
1020 			"move-words",
1021 			cast(GCallback)&callBackMoveWords,
1022 			cast(void*)onMoveWordsListeners[onMoveWordsListeners.length - 1],
1023 			cast(GClosureNotify)&callBackMoveWordsDestroy,
1024 			connectFlags);
1025 		return onMoveWordsListeners[onMoveWordsListeners.length - 1].handlerId;
1026 	}
1027 	
1028 	extern(C) static void callBackMoveWords(GtkSourceView* sourceviewStruct, int count,OnMoveWordsDelegateWrapper wrapper)
1029 	{
1030 		wrapper.dlg(count, wrapper.outer);
1031 	}
1032 	
1033 	extern(C) static void callBackMoveWordsDestroy(OnMoveWordsDelegateWrapper wrapper, GClosure* closure)
1034 	{
1035 		wrapper.outer.internalRemoveOnMoveWords(wrapper);
1036 	}
1037 
1038 	protected void internalRemoveOnMoveWords(OnMoveWordsDelegateWrapper source)
1039 	{
1040 		foreach(index, wrapper; onMoveWordsListeners)
1041 		{
1042 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
1043 			{
1044 				onMoveWordsListeners[index] = null;
1045 				onMoveWordsListeners = std.algorithm.remove(onMoveWordsListeners, index);
1046 				break;
1047 			}
1048 		}
1049 	}
1050 	
1051 
1052 	protected class OnRedoDelegateWrapper
1053 	{
1054 		void delegate(SourceView) dlg;
1055 		gulong handlerId;
1056 		ConnectFlags flags;
1057 		this(void delegate(SourceView) dlg, gulong handlerId, ConnectFlags flags)
1058 		{
1059 			this.dlg = dlg;
1060 			this.handlerId = handlerId;
1061 			this.flags = flags;
1062 		}
1063 	}
1064 	protected OnRedoDelegateWrapper[] onRedoListeners;
1065 
1066 	/** */
1067 	gulong addOnRedo(void delegate(SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1068 	{
1069 		onRedoListeners ~= new OnRedoDelegateWrapper(dlg, 0, connectFlags);
1070 		onRedoListeners[onRedoListeners.length - 1].handlerId = Signals.connectData(
1071 			this,
1072 			"redo",
1073 			cast(GCallback)&callBackRedo,
1074 			cast(void*)onRedoListeners[onRedoListeners.length - 1],
1075 			cast(GClosureNotify)&callBackRedoDestroy,
1076 			connectFlags);
1077 		return onRedoListeners[onRedoListeners.length - 1].handlerId;
1078 	}
1079 	
1080 	extern(C) static void callBackRedo(GtkSourceView* sourceviewStruct,OnRedoDelegateWrapper wrapper)
1081 	{
1082 		wrapper.dlg(wrapper.outer);
1083 	}
1084 	
1085 	extern(C) static void callBackRedoDestroy(OnRedoDelegateWrapper wrapper, GClosure* closure)
1086 	{
1087 		wrapper.outer.internalRemoveOnRedo(wrapper);
1088 	}
1089 
1090 	protected void internalRemoveOnRedo(OnRedoDelegateWrapper source)
1091 	{
1092 		foreach(index, wrapper; onRedoListeners)
1093 		{
1094 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
1095 			{
1096 				onRedoListeners[index] = null;
1097 				onRedoListeners = std.algorithm.remove(onRedoListeners, index);
1098 				break;
1099 			}
1100 		}
1101 	}
1102 	
1103 
1104 	protected class OnShowCompletionDelegateWrapper
1105 	{
1106 		void delegate(SourceView) dlg;
1107 		gulong handlerId;
1108 		ConnectFlags flags;
1109 		this(void delegate(SourceView) dlg, gulong handlerId, ConnectFlags flags)
1110 		{
1111 			this.dlg = dlg;
1112 			this.handlerId = handlerId;
1113 			this.flags = flags;
1114 		}
1115 	}
1116 	protected OnShowCompletionDelegateWrapper[] onShowCompletionListeners;
1117 
1118 	/**
1119 	 * The ::show-completion signal is a key binding signal which gets
1120 	 * emitted when the user requests a completion, by pressing
1121 	 * <keycombo><keycap>Control</keycap><keycap>space</keycap></keycombo>.
1122 	 *
1123 	 * This will create a #GtkSourceCompletionContext with the activation
1124 	 * type as %GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED.
1125 	 *
1126 	 * Applications should not connect to it, but may emit it with
1127 	 * g_signal_emit_by_name() if they need to activate the completion by
1128 	 * another means, for example with another key binding or a menu entry.
1129 	 */
1130 	gulong addOnShowCompletion(void delegate(SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1131 	{
1132 		onShowCompletionListeners ~= new OnShowCompletionDelegateWrapper(dlg, 0, connectFlags);
1133 		onShowCompletionListeners[onShowCompletionListeners.length - 1].handlerId = Signals.connectData(
1134 			this,
1135 			"show-completion",
1136 			cast(GCallback)&callBackShowCompletion,
1137 			cast(void*)onShowCompletionListeners[onShowCompletionListeners.length - 1],
1138 			cast(GClosureNotify)&callBackShowCompletionDestroy,
1139 			connectFlags);
1140 		return onShowCompletionListeners[onShowCompletionListeners.length - 1].handlerId;
1141 	}
1142 	
1143 	extern(C) static void callBackShowCompletion(GtkSourceView* sourceviewStruct,OnShowCompletionDelegateWrapper wrapper)
1144 	{
1145 		wrapper.dlg(wrapper.outer);
1146 	}
1147 	
1148 	extern(C) static void callBackShowCompletionDestroy(OnShowCompletionDelegateWrapper wrapper, GClosure* closure)
1149 	{
1150 		wrapper.outer.internalRemoveOnShowCompletion(wrapper);
1151 	}
1152 
1153 	protected void internalRemoveOnShowCompletion(OnShowCompletionDelegateWrapper source)
1154 	{
1155 		foreach(index, wrapper; onShowCompletionListeners)
1156 		{
1157 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
1158 			{
1159 				onShowCompletionListeners[index] = null;
1160 				onShowCompletionListeners = std.algorithm.remove(onShowCompletionListeners, index);
1161 				break;
1162 			}
1163 		}
1164 	}
1165 	
1166 
1167 	protected class OnSmartHomeEndDelegateWrapper
1168 	{
1169 		void delegate(TextIter, int, SourceView) dlg;
1170 		gulong handlerId;
1171 		ConnectFlags flags;
1172 		this(void delegate(TextIter, int, SourceView) dlg, gulong handlerId, ConnectFlags flags)
1173 		{
1174 			this.dlg = dlg;
1175 			this.handlerId = handlerId;
1176 			this.flags = flags;
1177 		}
1178 	}
1179 	protected OnSmartHomeEndDelegateWrapper[] onSmartHomeEndListeners;
1180 
1181 	/**
1182 	 * Emitted when a the cursor was moved according to the smart home
1183 	 * end setting. The signal is emitted after the cursor is moved, but
1184 	 * during the GtkTextView::move-cursor action. This can be used to find
1185 	 * out whether the cursor was moved by a normal home/end or by a smart
1186 	 * home/end.
1187 	 *
1188 	 * Params:
1189 	 *     iter = a #GtkTextIter
1190 	 *     count = the count
1191 	 *
1192 	 * Since: 3.0
1193 	 */
1194 	gulong addOnSmartHomeEnd(void delegate(TextIter, int, SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1195 	{
1196 		onSmartHomeEndListeners ~= new OnSmartHomeEndDelegateWrapper(dlg, 0, connectFlags);
1197 		onSmartHomeEndListeners[onSmartHomeEndListeners.length - 1].handlerId = Signals.connectData(
1198 			this,
1199 			"smart-home-end",
1200 			cast(GCallback)&callBackSmartHomeEnd,
1201 			cast(void*)onSmartHomeEndListeners[onSmartHomeEndListeners.length - 1],
1202 			cast(GClosureNotify)&callBackSmartHomeEndDestroy,
1203 			connectFlags);
1204 		return onSmartHomeEndListeners[onSmartHomeEndListeners.length - 1].handlerId;
1205 	}
1206 	
1207 	extern(C) static void callBackSmartHomeEnd(GtkSourceView* sourceviewStruct, GtkTextIter* iter, int count,OnSmartHomeEndDelegateWrapper wrapper)
1208 	{
1209 		wrapper.dlg(ObjectG.getDObject!(TextIter)(iter), count, wrapper.outer);
1210 	}
1211 	
1212 	extern(C) static void callBackSmartHomeEndDestroy(OnSmartHomeEndDelegateWrapper wrapper, GClosure* closure)
1213 	{
1214 		wrapper.outer.internalRemoveOnSmartHomeEnd(wrapper);
1215 	}
1216 
1217 	protected void internalRemoveOnSmartHomeEnd(OnSmartHomeEndDelegateWrapper source)
1218 	{
1219 		foreach(index, wrapper; onSmartHomeEndListeners)
1220 		{
1221 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
1222 			{
1223 				onSmartHomeEndListeners[index] = null;
1224 				onSmartHomeEndListeners = std.algorithm.remove(onSmartHomeEndListeners, index);
1225 				break;
1226 			}
1227 		}
1228 	}
1229 	
1230 
1231 	protected class OnUndoDelegateWrapper
1232 	{
1233 		void delegate(SourceView) dlg;
1234 		gulong handlerId;
1235 		ConnectFlags flags;
1236 		this(void delegate(SourceView) dlg, gulong handlerId, ConnectFlags flags)
1237 		{
1238 			this.dlg = dlg;
1239 			this.handlerId = handlerId;
1240 			this.flags = flags;
1241 		}
1242 	}
1243 	protected OnUndoDelegateWrapper[] onUndoListeners;
1244 
1245 	/** */
1246 	gulong addOnUndo(void delegate(SourceView) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1247 	{
1248 		onUndoListeners ~= new OnUndoDelegateWrapper(dlg, 0, connectFlags);
1249 		onUndoListeners[onUndoListeners.length - 1].handlerId = Signals.connectData(
1250 			this,
1251 			"undo",
1252 			cast(GCallback)&callBackUndo,
1253 			cast(void*)onUndoListeners[onUndoListeners.length - 1],
1254 			cast(GClosureNotify)&callBackUndoDestroy,
1255 			connectFlags);
1256 		return onUndoListeners[onUndoListeners.length - 1].handlerId;
1257 	}
1258 	
1259 	extern(C) static void callBackUndo(GtkSourceView* sourceviewStruct,OnUndoDelegateWrapper wrapper)
1260 	{
1261 		wrapper.dlg(wrapper.outer);
1262 	}
1263 	
1264 	extern(C) static void callBackUndoDestroy(OnUndoDelegateWrapper wrapper, GClosure* closure)
1265 	{
1266 		wrapper.outer.internalRemoveOnUndo(wrapper);
1267 	}
1268 
1269 	protected void internalRemoveOnUndo(OnUndoDelegateWrapper source)
1270 	{
1271 		foreach(index, wrapper; onUndoListeners)
1272 		{
1273 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
1274 			{
1275 				onUndoListeners[index] = null;
1276 				onUndoListeners = std.algorithm.remove(onUndoListeners, index);
1277 				break;
1278 			}
1279 		}
1280 	}
1281 	
1282 }