2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2004-2022 the Claws Mail team
4 * Copyright (C) 2014-2015 Charles Lehner
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "claws-features.h"
28 #include <glib/gi18n.h>
31 #include "gtk/gtkutils.h"
32 #include "gtk/combobox.h"
33 #include "gtk/manage_window.h"
34 #include "alertpanel.h"
39 #include "prefs_common.h"
41 #include "mainwindow.h"
42 #include "message_search.h"
43 #include "managesieve.h"
44 #include "sieve_manager.h"
45 #include "sieve_editor.h"
47 GSList
*editors
= NULL
;
49 static void sieve_editor_destroy(SieveEditorPage
*page
);
51 void sieve_editor_set_position(void *obj
, gint pos
);
52 gboolean
sieve_editor_search_string(void *obj
,
53 const gchar
*str
, gboolean case_sens
);
54 gboolean
sieve_editor_search_string_backward(void *obj
,
55 const gchar
*str
, gboolean case_sens
);
56 static void sieve_editor_save_cb(GtkAction
*action
, SieveEditorPage
*page
);
57 static void sieve_editor_check_cb(GtkAction
*action
, SieveEditorPage
*page
);
58 static void sieve_editor_changed_cb(GtkTextBuffer
*, SieveEditorPage
*page
);
59 static void sieve_editor_revert_cb(GtkAction
*action
, SieveEditorPage
*page
);
60 static void sieve_editor_close_cb(GtkAction
*action
, SieveEditorPage
*page
);
61 static void sieve_editor_undo_cb(GtkAction
*action
, SieveEditorPage
*page
);
62 static void sieve_editor_redo_cb(GtkAction
*action
, SieveEditorPage
*page
);
63 static void sieve_editor_cut_cb(GtkAction
*action
, SieveEditorPage
*page
);
64 static void sieve_editor_copy_cb(GtkAction
*action
, SieveEditorPage
*page
);
65 static void sieve_editor_paste_cb(GtkAction
*action
, SieveEditorPage
*page
);
66 static void sieve_editor_allsel_cb(GtkAction
*action
, SieveEditorPage
*page
);
67 static void sieve_editor_find_cb(GtkAction
*action
, SieveEditorPage
*page
);
68 static void sieve_editor_set_modified(SieveEditorPage
*page
,
71 static SearchInterface search_interface
= {
72 .set_position
= sieve_editor_set_position
,
73 .search_string_backward
= sieve_editor_search_string_backward
,
74 .search_string
= sieve_editor_search_string
,
77 static GtkActionEntry sieve_editor_entries
[] =
79 {"Menu", NULL
, "Menu", NULL
, NULL
, NULL
},
81 {"Filter", NULL
, N_("_Filter"), NULL
, NULL
, NULL
},
82 {"Edit", NULL
, N_("_Edit"), NULL
, NULL
, NULL
},
85 {"Filter/Save", NULL
, N_("_Save"), "<control>S", NULL
, G_CALLBACK(sieve_editor_save_cb
) },
86 {"Filter/CheckSyntax", NULL
, N_("Chec_k Syntax"), "<control>K", NULL
, G_CALLBACK(sieve_editor_check_cb
) },
87 {"Filter/Revert", NULL
, N_("Re_vert"), NULL
, NULL
, G_CALLBACK(sieve_editor_revert_cb
) },
88 {"Filter/Close", NULL
, N_("_Close"), "<control>W", NULL
, G_CALLBACK(sieve_editor_close_cb
) },
91 {"Edit/Undo", NULL
, N_("_Undo"), "<control>Z", NULL
, G_CALLBACK(sieve_editor_undo_cb
) },
92 {"Edit/Redo", NULL
, N_("_Redo"), "<control>Y", NULL
, G_CALLBACK(sieve_editor_redo_cb
) },
93 /* {"Edit/---", NULL, "---", NULL, NULL, NULL }, */
95 {"Edit/Cut", NULL
, N_("Cu_t"), "<control>X", NULL
, G_CALLBACK(sieve_editor_cut_cb
) },
96 {"Edit/Copy", NULL
, N_("_Copy"), "<control>C", NULL
, G_CALLBACK(sieve_editor_copy_cb
) },
97 {"Edit/Paste", NULL
, N_("_Paste"), "<control>V", NULL
, G_CALLBACK(sieve_editor_paste_cb
) },
99 {"Edit/SelectAll", NULL
, N_("Select _all"), "<control>A", NULL
, G_CALLBACK(sieve_editor_allsel_cb
) },
101 {"Edit/---", NULL
, "---", NULL
, NULL
, NULL
},
102 {"Edit/Find", NULL
, N_("_Find"), "<control>F", NULL
, G_CALLBACK(sieve_editor_find_cb
) },
106 void sieve_editors_close()
109 GSList
*list
= editors
;
111 g_slist_free_full(list
, (GDestroyNotify
)sieve_editor_close
);
115 void sieve_editor_append_text(SieveEditorPage
*page
, gchar
*text
, gint len
)
117 GtkTextBuffer
*buffer
;
120 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
122 g_signal_handlers_block_by_func(G_OBJECT(buffer
),
123 G_CALLBACK(sieve_editor_changed_cb
), page
);
125 undo_block(page
->undostruct
);
126 gtk_text_buffer_get_end_iter(buffer
, &iter
);
127 gtk_text_buffer_insert(buffer
, &iter
, text
, len
);
128 undo_unblock(page
->undostruct
);
130 g_signal_handlers_unblock_by_func(G_OBJECT(buffer
),
131 G_CALLBACK(sieve_editor_changed_cb
), page
);
134 static gint
sieve_editor_get_text(SieveEditorPage
*page
, gchar
**text
)
136 GtkTextBuffer
*buffer
;
137 GtkTextIter start
, end
;
139 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
140 gtk_text_buffer_get_start_iter(buffer
, &start
);
141 gtk_text_buffer_get_end_iter(buffer
, &end
);
142 *text
= gtk_text_buffer_get_text(buffer
, &start
, &end
, FALSE
);
143 /* return length in bytes */
144 return strlen(*text
);
147 static void sieve_editor_set_status(SieveEditorPage
*page
, const gchar
*status
)
149 gtk_label_set_text(GTK_LABEL(page
->status_text
), status
);
152 static void sieve_editor_set_status_icon(SieveEditorPage
*page
, const gchar
*img_id
)
154 GtkImage
*img
= GTK_IMAGE(page
->status_icon
);
156 gtk_image_set_from_icon_name(img
, img_id
, GTK_ICON_SIZE_BUTTON
);
158 gtk_image_clear(img
);
161 static void sieve_editor_append_status(SieveEditorPage
*page
,
162 const gchar
*new_status
)
164 GtkLabel
*label
= GTK_LABEL(page
->status_text
);
165 const gchar
*prev_status
= gtk_label_get_text(label
);
166 const gchar
*sep
= prev_status
&& prev_status
[0] ? "\n" : "";
167 gchar
*status
= g_strconcat(prev_status
? prev_status
: "", sep
, new_status
, NULL
);
168 gtk_label_set_text(label
, status
);
172 /* Update the status icon and text from a response. */
173 static void sieve_editor_update_status(SieveEditorPage
*page
,
176 if (result
->has_status
) {
177 /* set status icon */
178 sieve_editor_set_status_icon(page
,
179 result
->success
? "dialog-information" : "dialog-error");
180 /* clear status text */
181 sieve_editor_set_status(page
, "");
183 if (result
->description
) {
184 /* append to status */
185 sieve_editor_append_status(page
, result
->description
);
191 static void sieve_editor_undo_cb(GtkAction
*action
, SieveEditorPage
*page
)
193 undo_undo(page
->undostruct
);
196 static void sieve_editor_redo_cb(GtkAction
*action
, SieveEditorPage
*page
)
198 undo_redo(page
->undostruct
);
201 static void sieve_editor_cut_cb(GtkAction
*action
, SieveEditorPage
*page
)
203 GtkTextBuffer
*buf
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
204 GtkClipboard
*clipboard
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
);
205 gtk_text_buffer_cut_clipboard(buf
, clipboard
, TRUE
);
208 static void sieve_editor_copy_cb(GtkAction
*action
, SieveEditorPage
*page
)
210 GtkTextBuffer
*buf
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
211 GtkClipboard
*clipboard
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
);
212 gtk_text_buffer_copy_clipboard(buf
, clipboard
);
215 static void sieve_editor_paste_cb(GtkAction
*action
, SieveEditorPage
*page
)
217 if (!gtk_widget_has_focus(page
->text
))
220 GtkTextBuffer
*buf
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
221 GtkClipboard
*clipboard
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
);
222 gchar
*contents
= gtk_clipboard_wait_for_text(clipboard
);
223 GtkTextMark
*start_mark
= gtk_text_buffer_get_insert(buf
);
224 GtkTextIter start_iter
;
226 undo_paste_clipboard(GTK_TEXT_VIEW(page
->text
), page
->undostruct
);
227 gtk_text_buffer_delete_selection(buf
, FALSE
, TRUE
);
229 gtk_text_buffer_get_iter_at_mark(buf
, &start_iter
, start_mark
);
230 gtk_text_buffer_insert(buf
, &start_iter
, contents
, strlen(contents
));
234 static void sieve_editor_allsel_cb(GtkAction
*action
, SieveEditorPage
*page
)
236 GtkTextIter start
, end
;
237 GtkTextBuffer
*buffer
;
239 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
240 gtk_text_buffer_get_start_iter(buffer
, &start
);
241 gtk_text_buffer_get_end_iter(buffer
, &end
);
242 gtk_text_buffer_select_range(buffer
, &start
, &end
);
247 void sieve_editor_set_position(void *obj
, gint pos
)
249 SieveEditorPage
*page
= (SieveEditorPage
*)obj
;
250 GtkTextView
*text
= GTK_TEXT_VIEW(page
->text
);
252 gtkut_text_view_set_position(text
, pos
);
255 gboolean
sieve_editor_search_string(void *obj
,
256 const gchar
*str
, gboolean case_sens
)
258 SieveEditorPage
*page
= (SieveEditorPage
*)obj
;
259 GtkTextView
*text
= GTK_TEXT_VIEW(page
->text
);
261 return gtkut_text_view_search_string(text
, str
, case_sens
);
264 gboolean
sieve_editor_search_string_backward(void *obj
,
265 const gchar
*str
, gboolean case_sens
)
267 SieveEditorPage
*page
= (SieveEditorPage
*)obj
;
268 GtkTextView
*text
= GTK_TEXT_VIEW(page
->text
);
270 return gtkut_text_view_search_string_backward(text
, str
, case_sens
);
273 static void sieve_editor_search(SieveEditorPage
*page
)
275 message_search_other(&search_interface
, page
);
280 static void got_data_reverting(SieveSession
*session
, gboolean abort
,
282 SieveEditorPage
*page
)
286 if (contents
== NULL
) {
288 undo_unblock(page
->undostruct
);
289 gtk_widget_set_sensitive(page
->text
, TRUE
);
290 sieve_editor_set_status(page
, "");
291 sieve_editor_set_modified(page
, FALSE
);
294 if (contents
== (void *)-1) {
296 sieve_editor_set_status(page
, _("Unable to get script contents"));
297 sieve_editor_set_status_icon(page
, "dialog-error");
301 if (page
->first_line
) {
302 GtkTextIter start
, end
;
303 GtkTextBuffer
*buffer
;
305 page
->first_line
= FALSE
;
307 /* delete previous data */
308 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(page
->text
));
309 gtk_text_buffer_get_start_iter(buffer
, &start
);
310 gtk_text_buffer_get_end_iter(buffer
, &end
);
311 gtk_text_buffer_delete(buffer
, &start
, &end
);
314 gtk_text_buffer_insert(buffer
, &end
, contents
, strlen(contents
));
316 sieve_editor_append_text(page
, contents
, strlen(contents
));
320 static void sieve_editor_revert(SieveEditorPage
*page
)
322 undo_block(page
->undostruct
);
323 page
->first_line
= TRUE
;
324 gtk_widget_set_sensitive(page
->text
, FALSE
);
325 sieve_editor_set_status(page
, _("Reverting..."));
326 sieve_editor_set_status_icon(page
, NULL
);
327 sieve_session_get_script(page
->session
, page
->script_name
,
328 (sieve_session_data_cb_fn
)got_data_reverting
, page
);
331 static void sieve_editor_revert_cb(GtkAction
*action
, SieveEditorPage
*page
)
333 if (!page
->modified
||
334 alertpanel(_("Revert script"),
335 _("This script has been modified. Revert the unsaved changes?"),
336 NULL
, _("_Revert"), NULL
, NULL
, NULL
, _("_Cancel"),
337 ALERTFOCUS_FIRST
) == G_ALERTDEFAULT
)
338 sieve_editor_revert(page
);
341 static void got_data_saved(SieveSession
*session
, gboolean abort
,
342 SieveResult
*result
, SieveEditorPage
*page
)
346 if (result
->has_status
&& result
->success
) {
347 sieve_editor_set_modified(page
, FALSE
);
349 sieve_editor_close(page
);
352 /* use nice status message if there are no warnings */
353 if (result
->code
== SIEVE_CODE_NONE
) {
354 result
->description
= _("Script saved successfully.");
358 /* notify manager windows of newly created script */
359 page
->is_new
= FALSE
;
360 sieve_manager_script_created(session
,
364 sieve_editor_update_status(page
, result
);
367 static void sieve_editor_save(SieveEditorPage
*page
)
370 gint len
= sieve_editor_get_text(page
, &text
);
371 sieve_editor_set_status(page
, _("Saving..."));
372 sieve_editor_set_status_icon(page
, NULL
);
373 sieve_session_put_script(page
->session
, page
->script_name
, len
, text
,
374 (sieve_session_data_cb_fn
)got_data_saved
, page
);
378 static void sieve_editor_save_cb(GtkAction
*action
, SieveEditorPage
*page
)
380 sieve_editor_save(page
);
383 static void sieve_editor_find_cb(GtkAction
*action
, SieveEditorPage
*page
)
385 sieve_editor_search(page
);
388 static void got_data_checked(SieveSession
*session
, gboolean abort
,
389 SieveResult
*result
, SieveEditorPage
*page
)
393 sieve_editor_update_status(page
, result
);
396 static void sieve_editor_check_cb(GtkAction
*action
, SieveEditorPage
*page
)
399 gint len
= sieve_editor_get_text(page
, &text
);
400 sieve_editor_set_status(page
, _("Checking syntax..."));
401 sieve_editor_set_status_icon(page
, NULL
);
402 sieve_session_check_script(page
->session
, len
, text
,
403 (sieve_session_data_cb_fn
)got_data_checked
, page
);
407 static void sieve_editor_changed_cb(GtkTextBuffer
*textbuf
,
408 SieveEditorPage
*page
)
410 if (!page
->modified
) {
411 sieve_editor_set_modified(page
, TRUE
);
415 static void sieve_editor_destroy(SieveEditorPage
*page
)
417 gtk_widget_destroy(page
->window
);
418 undo_destroy(page
->undostruct
);
419 g_free(page
->script_name
);
423 void sieve_editor_close(SieveEditorPage
*page
)
425 editors
= g_slist_remove(editors
, (gconstpointer
)page
);
426 sieve_sessions_discard_callbacks(page
);
427 sieve_editor_destroy(page
);
430 static gboolean
sieve_editor_confirm_close(SieveEditorPage
*page
)
432 if (page
->modified
) {
433 switch (alertpanel(_("Save changes"),
434 _("This script has been modified. Save the latest changes?"),
435 NULL
, _("_Discard"), "document-save", _("_Save"), NULL
, _("_Cancel"),
436 ALERTFOCUS_SECOND
)) {
439 case G_ALERTALTERNATE
:
440 page
->closing
= TRUE
;
441 sieve_editor_save(page
);
450 static void sieve_editor_close_cb(GtkAction
*action
, SieveEditorPage
*page
)
452 if (sieve_editor_confirm_close(page
)) {
453 sieve_editor_close(page
);
457 static gint
sieve_editor_delete_cb(GtkWidget
*widget
, GdkEventAny
*event
,
458 SieveEditorPage
*page
)
460 sieve_editor_close_cb(NULL
, page
);
465 * sieve_editor_undo_state_changed:
467 * Change the sensivity of the menuentries undo and redo
469 static void sieve_editor_undo_state_changed(UndoMain
*undostruct
,
470 gint undo_state
, gint redo_state
, gpointer data
)
472 SieveEditorPage
*page
= (SieveEditorPage
*)data
;
474 switch (undo_state
) {
475 case UNDO_STATE_TRUE
:
476 if (!undostruct
->undo_state
) {
477 undostruct
->undo_state
= TRUE
;
478 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Undo", TRUE
);
481 case UNDO_STATE_FALSE
:
482 if (undostruct
->undo_state
) {
483 undostruct
->undo_state
= FALSE
;
484 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Undo", FALSE
);
487 case UNDO_STATE_UNCHANGED
:
489 case UNDO_STATE_REFRESH
:
490 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Undo", undostruct
->undo_state
);
493 g_warning("undo state not recognized");
497 switch (redo_state
) {
498 case UNDO_STATE_TRUE
:
499 if (!undostruct
->redo_state
) {
500 undostruct
->redo_state
= TRUE
;
501 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Redo", TRUE
);
504 case UNDO_STATE_FALSE
:
505 if (undostruct
->redo_state
) {
506 undostruct
->redo_state
= FALSE
;
507 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Redo", FALSE
);
510 case UNDO_STATE_UNCHANGED
:
512 case UNDO_STATE_REFRESH
:
513 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Edit/Redo", undostruct
->redo_state
);
516 g_warning("redo state not recognized");
522 SieveEditorPage
*sieve_editor_new(SieveSession
*session
, gchar
*script_name
)
524 SieveEditorPage
*page
;
525 GtkUIManager
*ui_manager
;
526 UndoMain
*undostruct
;
529 GtkWidget
*vbox
, *hbox
, *hbox1
;
530 GtkWidget
*scrolledwin
;
532 GtkTextBuffer
*buffer
;
533 GtkWidget
*check_btn
, *save_btn
, *close_btn
;
534 GtkWidget
*status_text
;
535 GtkWidget
*status_icon
;
537 page
= g_new0(SieveEditorPage
, 1);
540 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "sieveeditor");
541 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
542 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
543 g_signal_connect(G_OBJECT(window
), "delete_event",
544 G_CALLBACK(sieve_editor_delete_cb
), page
);
546 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
547 gtk_container_add(GTK_CONTAINER(window
), vbox
);
549 ui_manager
= gtk_ui_manager_new();
550 cm_menu_create_action_group_full(ui_manager
,
551 "Menu", sieve_editor_entries
, G_N_ELEMENTS(sieve_editor_entries
),
554 MENUITEM_ADDUI_MANAGER(ui_manager
, "/", "Menu", NULL
, GTK_UI_MANAGER_MENUBAR
)
556 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Filter", "Filter", GTK_UI_MANAGER_MENU
)
557 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Edit", "Edit", GTK_UI_MANAGER_MENU
)
560 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Filter", "Save", "Filter/Save", GTK_UI_MANAGER_MENUITEM
)
561 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Filter", "CheckSyntax", "Filter/CheckSyntax", GTK_UI_MANAGER_MENUITEM
)
562 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Filter", "Revert", "Filter/Revert", GTK_UI_MANAGER_MENUITEM
)
563 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Filter", "Close", "Filter/Close", GTK_UI_MANAGER_MENUITEM
)
566 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Undo", "Edit/Undo", GTK_UI_MANAGER_MENUITEM
)
567 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Redo", "Edit/Redo", GTK_UI_MANAGER_MENUITEM
)
568 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Separator1", "Edit/---", GTK_UI_MANAGER_SEPARATOR
)
570 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Cut", "Edit/Cut", GTK_UI_MANAGER_MENUITEM
)
571 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Copy", "Edit/Copy", GTK_UI_MANAGER_MENUITEM
)
572 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Paste", "Edit/Paste", GTK_UI_MANAGER_MENUITEM
)
574 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "SelectAll", "Edit/SelectAll", GTK_UI_MANAGER_MENUITEM
)
576 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Separator2", "Edit/---", GTK_UI_MANAGER_SEPARATOR
)
578 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Edit", "Find", "Edit/Find", GTK_UI_MANAGER_MENUITEM
)
580 menubar
= gtk_ui_manager_get_widget(ui_manager
, "/Menu");
582 gtk_window_add_accel_group(GTK_WINDOW(window
), gtk_ui_manager_get_accel_group(ui_manager
));
583 gtk_box_pack_start(GTK_BOX(vbox
), menubar
, FALSE
, TRUE
, 0);
585 cm_menu_set_sensitive_full(ui_manager
, "Menu/Edit/Undo", FALSE
);
586 cm_menu_set_sensitive_full(ui_manager
, "Menu/Edit/Redo", FALSE
);
589 scrolledwin
= gtk_scrolled_window_new(NULL
, NULL
);
590 gtk_widget_set_size_request (scrolledwin
, 660, 408);
591 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin
),
592 GTK_POLICY_AUTOMATIC
,
593 GTK_POLICY_AUTOMATIC
);
594 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin
),
596 gtk_box_pack_start(GTK_BOX(vbox
), scrolledwin
, TRUE
, TRUE
, 0);
598 text
= gtk_text_view_new();
599 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text
), GTK_WRAP_WORD_CHAR
);
600 gtk_text_view_set_editable(GTK_TEXT_VIEW(text
), TRUE
);
601 gtk_container_add(GTK_CONTAINER(scrolledwin
), text
);
603 buffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(text
));
604 g_signal_connect(G_OBJECT(buffer
), "changed",
605 G_CALLBACK(sieve_editor_changed_cb
), page
);
608 if (prefs_common_get_prefs()->textfont
) {
609 PangoFontDescription
*font_desc
;
611 font_desc
= pango_font_description_from_string
612 (prefs_common_get_prefs()->textfont
);
614 gtk_widget_override_font(text
, font_desc
);
615 pango_font_description_free(font_desc
);
619 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 8);
620 gtk_box_pack_end (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
621 gtk_container_set_border_width (GTK_CONTAINER (hbox
), 8);
624 status_icon
= gtk_image_new ();
625 gtk_box_pack_start (GTK_BOX (hbox
), status_icon
, FALSE
, FALSE
, 0);
626 status_text
= gtk_label_new ("");
627 gtk_box_pack_start (GTK_BOX (hbox
), status_text
, FALSE
, FALSE
, 0);
628 gtk_label_set_justify (GTK_LABEL (status_text
), GTK_JUSTIFY_LEFT
);
631 gtkut_stock_with_text_button_set_create(&hbox1
,
632 &close_btn
, _("_Cancel"), _("_Close"),
633 &check_btn
, _("_OK"), _("Chec_k Syntax"),
634 &save_btn
, "document-save", _("_Save"));
635 gtk_box_pack_end (GTK_BOX (hbox
), hbox1
, FALSE
, FALSE
, 0);
636 gtk_widget_grab_default (save_btn
);
637 g_signal_connect (G_OBJECT (close_btn
), "clicked",
638 G_CALLBACK (sieve_editor_close_cb
), page
);
639 g_signal_connect (G_OBJECT (check_btn
), "clicked",
640 G_CALLBACK (sieve_editor_check_cb
), page
);
641 g_signal_connect (G_OBJECT (save_btn
), "clicked",
642 G_CALLBACK (sieve_editor_save_cb
), page
);
644 undostruct
= undo_init(text
);
645 undo_set_change_state_func(undostruct
, &sieve_editor_undo_state_changed
,
648 page
->window
= window
;
649 page
->ui_manager
= ui_manager
;
651 page
->undostruct
= undostruct
;
652 page
->session
= session
;
653 page
->script_name
= script_name
;
654 page
->status_text
= status_text
;
655 page
->status_icon
= status_icon
;
657 editors
= g_slist_prepend(editors
, page
);
659 sieve_editor_set_modified(page
, FALSE
);
664 SieveEditorPage
*sieve_editor_get(SieveSession
*session
, gchar
*script_name
)
667 SieveEditorPage
*page
;
668 for (item
= editors
; item
; item
= item
->next
) {
669 page
= (SieveEditorPage
*)item
->data
;
670 if (page
->session
== session
&&
671 strcmp(script_name
, page
->script_name
) == 0)
677 void sieve_editor_present(SieveEditorPage
*page
)
679 gtk_window_present(GTK_WINDOW(page
->window
));
682 void sieve_editor_show(SieveEditorPage
*page
)
684 gtk_widget_show_all(GTK_WIDGET(page
->window
));
687 static void sieve_editor_set_modified(SieveEditorPage
*page
,
692 page
->modified
= modified
;
693 cm_menu_set_sensitive_full(page
->ui_manager
, "Menu/Filter/Revert",
696 title
= g_strdup_printf(_("%s - Sieve Filter%s"), page
->script_name
,
697 modified
? _(" [Edited]") : "");
698 gtk_window_set_title (GTK_WINDOW (page
->window
), title
);
702 sieve_editor_set_status(page
, "");
703 sieve_editor_set_status_icon(page
, NULL
);
707 static void got_data_loading(SieveSession
*session
, gboolean aborted
,
708 gchar
*contents
, SieveEditorPage
*page
)
712 if (contents
== NULL
) {
714 sieve_editor_set_status(page
, "");
717 if (contents
== (void *)-1) {
719 if (page
->first_line
) {
720 /* no data. show error in manager window */
721 if (page
->on_load_error
)
722 page
->on_load_error(session
, page
->on_load_error_data
);
724 /* partial failure. show error in editor window */
725 sieve_editor_set_status(page
, _("Unable to get script contents"));
726 sieve_editor_set_status_icon(page
, "dialog-error");
731 if (page
->first_line
) {
732 page
->first_line
= FALSE
;
733 sieve_editor_show(page
);
735 sieve_editor_append_text(page
, contents
, strlen(contents
));
738 /* load the script for this editor */
739 void sieve_editor_load(SieveEditorPage
*page
,
740 sieve_session_cb_fn on_load_error
, gpointer load_error_data
)
742 page
->first_line
= TRUE
;
743 page
->on_load_error
= on_load_error
;
744 page
->on_load_error_data
= load_error_data
;
745 sieve_editor_set_status(page
, _("Loading..."));
746 sieve_editor_set_status_icon(page
, NULL
);
747 sieve_session_get_script(page
->session
, page
->script_name
,
748 (sieve_session_data_cb_fn
)got_data_loading
, page
);