Mercurial > pidgin.yaz
comparison pidgin/gtksourceundomanager.c @ 22674:27c9c55499f8
Smiley insertions can be undone with this fix. References #5577. But redo
doesn't work yet.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sun, 20 Apr 2008 15:35:16 +0000 |
parents | 44b4e8bd759b |
children | 7fc110f70662 |
comparison
equal
deleted
inserted
replaced
22672:269bba623a62 | 22674:27c9c55499f8 |
---|---|
39 | 39 |
40 | 40 |
41 typedef struct _GtkSourceUndoAction GtkSourceUndoAction; | 41 typedef struct _GtkSourceUndoAction GtkSourceUndoAction; |
42 typedef struct _GtkSourceUndoInsertAction GtkSourceUndoInsertAction; | 42 typedef struct _GtkSourceUndoInsertAction GtkSourceUndoInsertAction; |
43 typedef struct _GtkSourceUndoDeleteAction GtkSourceUndoDeleteAction; | 43 typedef struct _GtkSourceUndoDeleteAction GtkSourceUndoDeleteAction; |
44 typedef struct _GtkSourceUndoInsertAnchorAction GtkSourceUndoInsertAnchorAction; | |
44 | 45 |
45 typedef enum { | 46 typedef enum { |
46 GTK_SOURCE_UNDO_ACTION_INSERT, | 47 GTK_SOURCE_UNDO_ACTION_INSERT, |
47 GTK_SOURCE_UNDO_ACTION_DELETE | 48 GTK_SOURCE_UNDO_ACTION_DELETE, |
49 GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR, | |
48 } GtkSourceUndoActionType; | 50 } GtkSourceUndoActionType; |
49 | 51 |
50 /* | 52 /* |
51 * We use offsets instead of GtkTextIters because the last ones | 53 * We use offsets instead of GtkTextIters because the last ones |
52 * require to much memory in this context without giving us any advantage. | 54 * require to much memory in this context without giving us any advantage. |
66 gint end; | 68 gint end; |
67 gchar *text; | 69 gchar *text; |
68 gboolean forward; | 70 gboolean forward; |
69 }; | 71 }; |
70 | 72 |
73 struct _GtkSourceUndoInsertAnchorAction | |
74 { | |
75 gint pos; | |
76 GtkTextChildAnchor *anchor; | |
77 }; | |
78 | |
71 struct _GtkSourceUndoAction | 79 struct _GtkSourceUndoAction |
72 { | 80 { |
73 GtkSourceUndoActionType action_type; | 81 GtkSourceUndoActionType action_type; |
74 | 82 |
75 union { | 83 union { |
76 GtkSourceUndoInsertAction insert; | 84 GtkSourceUndoInsertAction insert; |
77 GtkSourceUndoDeleteAction delete; | 85 GtkSourceUndoDeleteAction delete; |
86 GtkSourceUndoInsertAnchorAction insert_anchor; | |
78 } action; | 87 } action; |
79 | 88 |
80 gint order_in_group; | 89 gint order_in_group; |
81 | 90 |
82 /* It is TRUE whether the action can be merged with the following action. */ | 91 /* It is TRUE whether the action can be merged with the following action. */ |
137 static void gtk_source_undo_manager_insert_text_handler (GtkTextBuffer *buffer, | 146 static void gtk_source_undo_manager_insert_text_handler (GtkTextBuffer *buffer, |
138 GtkTextIter *pos, | 147 GtkTextIter *pos, |
139 const gchar *text, | 148 const gchar *text, |
140 gint length, | 149 gint length, |
141 GtkSourceUndoManager *um); | 150 GtkSourceUndoManager *um); |
151 static void gtk_source_undo_manager_insert_anchor_handler (GtkTextBuffer *buffer, | |
152 GtkTextIter *pos, | |
153 GtkTextChildAnchor *anchor, | |
154 GtkSourceUndoManager *um); | |
142 static void gtk_source_undo_manager_delete_range_handler (GtkTextBuffer *buffer, | 155 static void gtk_source_undo_manager_delete_range_handler (GtkTextBuffer *buffer, |
143 GtkTextIter *start, | 156 GtkTextIter *start, |
144 GtkTextIter *end, | 157 GtkTextIter *end, |
145 GtkSourceUndoManager *um); | 158 GtkSourceUndoManager *um); |
146 static void gtk_source_undo_manager_begin_user_action_handler (GtkTextBuffer *buffer, | 159 static void gtk_source_undo_manager_begin_user_action_handler (GtkTextBuffer *buffer, |
273 g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), | 286 g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), |
274 G_CALLBACK (gtk_source_undo_manager_insert_text_handler), | 287 G_CALLBACK (gtk_source_undo_manager_insert_text_handler), |
275 um); | 288 um); |
276 | 289 |
277 g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), | 290 g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), |
291 G_CALLBACK (gtk_source_undo_manager_insert_anchor_handler), | |
292 um); | |
293 | |
294 g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), | |
278 G_CALLBACK (gtk_source_undo_manager_begin_user_action_handler), | 295 G_CALLBACK (gtk_source_undo_manager_begin_user_action_handler), |
279 um); | 296 um); |
280 | 297 |
281 g_free (um->priv); | 298 g_free (um->priv); |
282 | 299 |
293 g_return_val_if_fail (um->priv != NULL, NULL); | 310 g_return_val_if_fail (um->priv != NULL, NULL); |
294 um->priv->document = buffer; | 311 um->priv->document = buffer; |
295 | 312 |
296 g_signal_connect (G_OBJECT (buffer), "insert_text", | 313 g_signal_connect (G_OBJECT (buffer), "insert_text", |
297 G_CALLBACK (gtk_source_undo_manager_insert_text_handler), | 314 G_CALLBACK (gtk_source_undo_manager_insert_text_handler), |
315 um); | |
316 | |
317 g_signal_connect (G_OBJECT (buffer), "insert_child_anchor", | |
318 G_CALLBACK (gtk_source_undo_manager_insert_anchor_handler), | |
298 um); | 319 um); |
299 | 320 |
300 g_signal_connect (G_OBJECT (buffer), "delete_range", | 321 g_signal_connect (G_OBJECT (buffer), "delete_range", |
301 G_CALLBACK (gtk_source_undo_manager_delete_range_handler), | 322 G_CALLBACK (gtk_source_undo_manager_delete_range_handler), |
302 um); | 323 um); |
398 { | 419 { |
399 GtkTextIter iter; | 420 GtkTextIter iter; |
400 | 421 |
401 gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos); | 422 gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos); |
402 gtk_text_buffer_insert (buffer, &iter, text, len); | 423 gtk_text_buffer_insert (buffer, &iter, text, len); |
424 } | |
425 | |
426 static void | |
427 insert_anchor (GtkTextBuffer *buffer, gint pos, GtkTextChildAnchor *anchor) | |
428 { | |
429 GtkTextIter iter; | |
430 | |
431 gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos); | |
432 gtk_text_buffer_insert_child_anchor (buffer, &iter, anchor); | |
403 } | 433 } |
404 | 434 |
405 static void | 435 static void |
406 delete_text (GtkTextBuffer *buffer, gint start, gint end) | 436 delete_text (GtkTextBuffer *buffer, gint start, gint end) |
407 { | 437 { |
495 set_cursor ( | 525 set_cursor ( |
496 um->priv->document, | 526 um->priv->document, |
497 undo_action->action.insert.pos); | 527 undo_action->action.insert.pos); |
498 break; | 528 break; |
499 | 529 |
530 case GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR: | |
531 delete_text ( | |
532 um->priv->document, | |
533 undo_action->action.insert_anchor.pos, | |
534 undo_action->action.insert_anchor.pos + 1); | |
535 undo_action->action.insert_anchor.anchor->segment = NULL; /* XXX: This may be a bug in GTK+ */ | |
536 break; | |
500 default: | 537 default: |
501 /* Unknown action type. */ | 538 /* Unknown action type. */ |
502 g_return_if_reached (); | 539 g_return_if_reached (); |
503 } | 540 } |
504 | 541 |
586 undo_action->action.insert.text, | 623 undo_action->action.insert.text, |
587 undo_action->action.insert.length); | 624 undo_action->action.insert.length); |
588 | 625 |
589 break; | 626 break; |
590 | 627 |
628 case GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR: | |
629 set_cursor ( | |
630 um->priv->document, | |
631 undo_action->action.insert_anchor.pos); | |
632 | |
633 insert_anchor ( | |
634 um->priv->document, | |
635 undo_action->action.insert_anchor.pos, | |
636 undo_action->action.insert_anchor.anchor); | |
637 break; | |
638 | |
591 default: | 639 default: |
592 /* Unknown action type */ | 640 /* Unknown action type */ |
593 ++um->priv->next_redo; | 641 ++um->priv->next_redo; |
594 g_return_if_reached (); | 642 g_return_if_reached (); |
595 } | 643 } |
631 | 679 |
632 if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) | 680 if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) |
633 g_free (action->action.insert.text); | 681 g_free (action->action.insert.text); |
634 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) | 682 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) |
635 g_free (action->action.delete.text); | 683 g_free (action->action.delete.text); |
684 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR) | |
685 g_object_unref(action->action.insert_anchor.anchor); | |
636 else | 686 else |
637 g_return_if_reached (); | 687 g_return_if_reached (); |
638 | 688 |
639 g_free (action); | 689 g_free (action); |
640 } | 690 } |
688 | 738 |
689 undo_action.mergeable = FALSE; | 739 undo_action.mergeable = FALSE; |
690 else | 740 else |
691 undo_action.mergeable = TRUE; | 741 undo_action.mergeable = TRUE; |
692 | 742 |
743 undo_action.modified = FALSE; | |
744 | |
745 gtk_source_undo_manager_add_action (um, &undo_action); | |
746 } | |
747 | |
748 static void gtk_source_undo_manager_insert_anchor_handler (GtkTextBuffer *buffer, | |
749 GtkTextIter *pos, | |
750 GtkTextChildAnchor *anchor, | |
751 GtkSourceUndoManager *um) | |
752 { | |
753 GtkSourceUndoAction undo_action; | |
754 | |
755 if (um->priv->running_not_undoable_actions > 0) | |
756 return; | |
757 | |
758 undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR; | |
759 | |
760 undo_action.action.insert_anchor.pos = gtk_text_iter_get_offset (pos); | |
761 undo_action.action.insert_anchor.anchor = g_object_ref (anchor); | |
762 | |
763 undo_action.mergeable = FALSE; | |
693 undo_action.modified = FALSE; | 764 undo_action.modified = FALSE; |
694 | 765 |
695 gtk_source_undo_manager_add_action (um, &undo_action); | 766 gtk_source_undo_manager_add_action (um, &undo_action); |
696 } | 767 } |
697 | 768 |
773 | 844 |
774 if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) | 845 if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) |
775 action->action.insert.text = g_strndup (undo_action->action.insert.text, undo_action->action.insert.length); | 846 action->action.insert.text = g_strndup (undo_action->action.insert.text, undo_action->action.insert.length); |
776 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) | 847 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) |
777 action->action.delete.text = g_strdup (undo_action->action.delete.text); | 848 action->action.delete.text = g_strdup (undo_action->action.delete.text); |
849 else if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR) | |
850 { | |
851 /* Nothing needs to be done */ | |
852 } | |
778 else | 853 else |
779 { | 854 { |
780 g_free (action); | 855 g_free (action); |
781 g_return_if_reached (); | 856 g_return_if_reached (); |
782 } | 857 } |
996 last_action->action.insert.length += undo_action->action.insert.length; | 1071 last_action->action.insert.length += undo_action->action.insert.length; |
997 last_action->action.insert.text = str; | 1072 last_action->action.insert.text = str; |
998 last_action->action.insert.chars += undo_action->action.insert.chars; | 1073 last_action->action.insert.chars += undo_action->action.insert.chars; |
999 | 1074 |
1000 } | 1075 } |
1076 else if (undo_action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT_ANCHOR) | |
1077 { | |
1078 /* Nothing needs to be done */ | |
1079 } | |
1001 else | 1080 else |
1002 /* Unknown action inside undo merge encountered */ | 1081 /* Unknown action inside undo merge encountered */ |
1003 g_return_val_if_reached (TRUE); | 1082 g_return_val_if_reached (TRUE); |
1004 | 1083 |
1005 return TRUE; | 1084 return TRUE; |