749 lines
23 KiB
C
749 lines
23 KiB
C
/*
|
|
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
|
|
* Copyright (C) 2004-2015 the Claws Mail team
|
|
* Copyright (C) 2014-2015 Charles Lehner
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#include "claws-features.h"
|
|
#endif
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <glib.h>
|
|
#include <glib/gi18n.h>
|
|
|
|
#include "defs.h"
|
|
#include "gtk/gtkutils.h"
|
|
#include "gtk/combobox.h"
|
|
#include "gtk/manage_window.h"
|
|
#include "alertpanel.h"
|
|
#include "undo.h"
|
|
#include "menu.h"
|
|
#include "utils.h"
|
|
#include "prefs.h"
|
|
#include "prefs_common.h"
|
|
#include "account.h"
|
|
#include "mainwindow.h"
|
|
#include "message_search.h"
|
|
#include "managesieve.h"
|
|
#include "sieve_manager.h"
|
|
#include "sieve_editor.h"
|
|
|
|
GSList *editors = NULL;
|
|
|
|
static void sieve_editor_destroy(SieveEditorPage *page);
|
|
|
|
void sieve_editor_set_position(void *obj, gint pos);
|
|
gboolean sieve_editor_search_string(void *obj,
|
|
const gchar *str, gboolean case_sens);
|
|
gboolean sieve_editor_search_string_backward(void *obj,
|
|
const gchar *str, gboolean case_sens);
|
|
static void sieve_editor_save_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_check_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_changed_cb(GtkTextBuffer *, SieveEditorPage *page);
|
|
static void sieve_editor_revert_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_close_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_undo_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_redo_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_cut_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_copy_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_paste_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_allsel_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_find_cb(GtkAction *action, SieveEditorPage *page);
|
|
static void sieve_editor_set_modified(SieveEditorPage *page,
|
|
gboolean modified);
|
|
|
|
static SearchInterface search_interface = {
|
|
.set_position = sieve_editor_set_position,
|
|
.search_string_backward = sieve_editor_search_string_backward,
|
|
.search_string = sieve_editor_search_string,
|
|
};
|
|
|
|
static GtkActionEntry sieve_editor_entries[] =
|
|
{
|
|
{"Menu", NULL, "Menu" },
|
|
/* menus */
|
|
{"Filter", NULL, N_("_Filter") },
|
|
{"Edit", NULL, N_("_Edit") },
|
|
/* Filter menu */
|
|
|
|
{"Filter/Save", NULL, N_("_Save"), "<control>S", NULL, G_CALLBACK(sieve_editor_save_cb) },
|
|
{"Filter/CheckSyntax", NULL, N_("Chec_k Syntax"), "<control>K", NULL, G_CALLBACK(sieve_editor_check_cb) },
|
|
{"Filter/Revert", NULL, N_("Re_vert"), NULL, NULL, G_CALLBACK(sieve_editor_revert_cb) },
|
|
{"Filter/Close", NULL, N_("_Close"), "<control>W", NULL, G_CALLBACK(sieve_editor_close_cb) },
|
|
|
|
/* Edit menu */
|
|
{"Edit/Undo", NULL, N_("_Undo"), "<control>Z", NULL, G_CALLBACK(sieve_editor_undo_cb) },
|
|
{"Edit/Redo", NULL, N_("_Redo"), "<control>Y", NULL, G_CALLBACK(sieve_editor_redo_cb) },
|
|
/* {"Edit/---", NULL, "---" }, */
|
|
|
|
{"Edit/Cut", NULL, N_("Cu_t"), "<control>X", NULL, G_CALLBACK(sieve_editor_cut_cb) },
|
|
{"Edit/Copy", NULL, N_("_Copy"), "<control>C", NULL, G_CALLBACK(sieve_editor_copy_cb) },
|
|
{"Edit/Paste", NULL, N_("_Paste"), "<control>V", NULL, G_CALLBACK(sieve_editor_paste_cb) },
|
|
|
|
{"Edit/SelectAll", NULL, N_("Select _all"), "<control>A", NULL, G_CALLBACK(sieve_editor_allsel_cb) },
|
|
|
|
{"Edit/---", NULL, "---" },
|
|
{"Edit/Find", NULL, N_("_Find"), "<control>F", NULL, G_CALLBACK(sieve_editor_find_cb) },
|
|
};
|
|
|
|
|
|
void sieve_editors_close()
|
|
{
|
|
if (editors) {
|
|
GSList *list = editors;
|
|
editors = NULL;
|
|
g_slist_free_full(list, (GDestroyNotify)sieve_editor_close);
|
|
}
|
|
}
|
|
|
|
void sieve_editor_append_text(SieveEditorPage *page, gchar *text, gint len)
|
|
{
|
|
GtkTextBuffer *buffer;
|
|
GtkTextIter iter;
|
|
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
|
|
g_signal_handlers_block_by_func(G_OBJECT(buffer),
|
|
G_CALLBACK(sieve_editor_changed_cb), page);
|
|
|
|
undo_block(page->undostruct);
|
|
gtk_text_buffer_get_end_iter(buffer, &iter);
|
|
gtk_text_buffer_insert(buffer, &iter, text, len);
|
|
undo_unblock(page->undostruct);
|
|
|
|
g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
|
|
G_CALLBACK(sieve_editor_changed_cb), page);
|
|
}
|
|
|
|
static gint sieve_editor_get_text(SieveEditorPage *page, gchar **text)
|
|
{
|
|
GtkTextBuffer *buffer;
|
|
GtkTextIter start, end;
|
|
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
gtk_text_buffer_get_start_iter(buffer, &start);
|
|
gtk_text_buffer_get_end_iter(buffer, &end);
|
|
*text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
|
|
/* return length in bytes */
|
|
return strlen(*text);
|
|
}
|
|
|
|
static void sieve_editor_set_status(SieveEditorPage *page, const gchar *status)
|
|
{
|
|
gtk_label_set_text(GTK_LABEL(page->status_text), status);
|
|
}
|
|
|
|
static void sieve_editor_set_status_icon(SieveEditorPage *page, const gchar *img_id)
|
|
{
|
|
GtkImage *img = GTK_IMAGE(page->status_icon);
|
|
if (img_id)
|
|
gtk_image_set_from_stock(img, img_id, GTK_ICON_SIZE_BUTTON);
|
|
else
|
|
gtk_image_clear(img);
|
|
}
|
|
|
|
static void sieve_editor_append_status(SieveEditorPage *page,
|
|
const gchar *new_status)
|
|
{
|
|
GtkLabel *label = GTK_LABEL(page->status_text);
|
|
const gchar *prev_status = gtk_label_get_text(label);
|
|
const gchar *sep = prev_status && prev_status[0] ? "\n" : "";
|
|
gchar *status = g_strconcat(prev_status, sep, new_status, NULL);
|
|
gtk_label_set_text(label, status);
|
|
g_free(status);
|
|
}
|
|
|
|
/* Update the status icon and text from a response. */
|
|
static void sieve_editor_update_status(SieveEditorPage *page,
|
|
SieveResult *result)
|
|
{
|
|
if (result->has_status) {
|
|
/* set status icon */
|
|
sieve_editor_set_status_icon(page,
|
|
result->success ? GTK_STOCK_DIALOG_INFO : GTK_STOCK_DIALOG_ERROR);
|
|
/* clear status text */
|
|
sieve_editor_set_status(page, "");
|
|
}
|
|
if (result->description) {
|
|
/* append to status */
|
|
sieve_editor_append_status(page, result->description);
|
|
}
|
|
}
|
|
|
|
/* Edit Menu */
|
|
|
|
static void sieve_editor_undo_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
undo_undo(page->undostruct);
|
|
}
|
|
|
|
static void sieve_editor_redo_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
undo_redo(page->undostruct);
|
|
}
|
|
|
|
static void sieve_editor_cut_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
|
gtk_text_buffer_cut_clipboard(buf, clipboard, TRUE);
|
|
}
|
|
|
|
static void sieve_editor_copy_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
|
gtk_text_buffer_copy_clipboard(buf, clipboard);
|
|
}
|
|
|
|
static void sieve_editor_paste_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
if (!gtk_widget_has_focus(page->text))
|
|
return;
|
|
|
|
GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
|
gchar *contents = gtk_clipboard_wait_for_text(clipboard);
|
|
GtkTextMark *start_mark = gtk_text_buffer_get_insert(buf);
|
|
GtkTextIter start_iter;
|
|
|
|
undo_paste_clipboard(GTK_TEXT_VIEW(page->text), page->undostruct);
|
|
gtk_text_buffer_delete_selection(buf, FALSE, TRUE);
|
|
|
|
gtk_text_buffer_get_iter_at_mark(buf, &start_iter, start_mark);
|
|
gtk_text_buffer_insert(buf, &start_iter, contents, strlen(contents));
|
|
}
|
|
|
|
|
|
static void sieve_editor_allsel_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
GtkTextIter start, end;
|
|
GtkTextBuffer *buffer;
|
|
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
gtk_text_buffer_get_start_iter(buffer, &start);
|
|
gtk_text_buffer_get_end_iter(buffer, &end);
|
|
gtk_text_buffer_select_range(buffer, &start, &end);
|
|
}
|
|
|
|
/* Search */
|
|
|
|
void sieve_editor_set_position(void *obj, gint pos)
|
|
{
|
|
SieveEditorPage *page = (SieveEditorPage *)obj;
|
|
GtkTextView *text = GTK_TEXT_VIEW(page->text);
|
|
|
|
gtkut_text_view_set_position(text, pos);
|
|
}
|
|
|
|
gboolean sieve_editor_search_string(void *obj,
|
|
const gchar *str, gboolean case_sens)
|
|
{
|
|
SieveEditorPage *page = (SieveEditorPage *)obj;
|
|
GtkTextView *text = GTK_TEXT_VIEW(page->text);
|
|
|
|
return gtkut_text_view_search_string(text, str, case_sens);
|
|
}
|
|
|
|
gboolean sieve_editor_search_string_backward(void *obj,
|
|
const gchar *str, gboolean case_sens)
|
|
{
|
|
SieveEditorPage *page = (SieveEditorPage *)obj;
|
|
GtkTextView *text = GTK_TEXT_VIEW(page->text);
|
|
|
|
return gtkut_text_view_search_string_backward(text, str, case_sens);
|
|
}
|
|
|
|
static void sieve_editor_search(SieveEditorPage *page)
|
|
{
|
|
message_search_other(&search_interface, page);
|
|
}
|
|
|
|
/* Actions */
|
|
|
|
static void got_data_reverting(SieveSession *session, gboolean abort,
|
|
gchar *contents,
|
|
SieveEditorPage *page)
|
|
{
|
|
if (abort)
|
|
return;
|
|
if (contents == NULL) {
|
|
/* end of data */
|
|
undo_unblock(page->undostruct);
|
|
gtk_widget_set_sensitive(page->text, TRUE);
|
|
sieve_editor_set_status(page, "");
|
|
sieve_editor_set_modified(page, FALSE);
|
|
return;
|
|
}
|
|
if (contents == (void *)-1) {
|
|
/* error */
|
|
sieve_editor_set_status(page, _("Unable to get script contents"));
|
|
sieve_editor_set_status_icon(page, GTK_STOCK_DIALOG_ERROR);
|
|
return;
|
|
}
|
|
|
|
if (page->first_line) {
|
|
GtkTextIter start, end;
|
|
GtkTextBuffer *buffer;
|
|
|
|
page->first_line = FALSE;
|
|
|
|
/* delete previous data */
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page->text));
|
|
gtk_text_buffer_get_start_iter(buffer, &start);
|
|
gtk_text_buffer_get_end_iter(buffer, &end);
|
|
gtk_text_buffer_delete(buffer, &start, &end);
|
|
|
|
/* append data */
|
|
gtk_text_buffer_insert(buffer, &end, contents, strlen(contents));
|
|
} else {
|
|
sieve_editor_append_text(page, "\n", 1);
|
|
sieve_editor_append_text(page, contents, strlen(contents));
|
|
}
|
|
}
|
|
|
|
static void sieve_editor_revert(SieveEditorPage *page)
|
|
{
|
|
undo_block(page->undostruct);
|
|
page->first_line = TRUE;
|
|
gtk_widget_set_sensitive(page->text, FALSE);
|
|
sieve_editor_set_status(page, _("Reverting..."));
|
|
sieve_editor_set_status_icon(page, NULL);
|
|
sieve_session_get_script(page->session, page->script_name,
|
|
(sieve_session_data_cb_fn)got_data_reverting, page);
|
|
}
|
|
|
|
static void sieve_editor_revert_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
if (!page->modified ||
|
|
alertpanel(_("Revert script"),
|
|
_("This script has been modified. Revert the unsaved changes?"),
|
|
_("_Revert"), NULL, GTK_STOCK_CANCEL) == G_ALERTDEFAULT)
|
|
sieve_editor_revert(page);
|
|
}
|
|
|
|
static void got_data_saved(SieveSession *session, gboolean abort,
|
|
SieveResult *result, SieveEditorPage *page)
|
|
{
|
|
if (abort)
|
|
return;
|
|
if (result->has_status && result->success) {
|
|
sieve_editor_set_modified(page, FALSE);
|
|
if (page->closing) {
|
|
sieve_editor_close(page);
|
|
return;
|
|
}
|
|
/* use nice status message if there are no warnings */
|
|
if (result->code == SIEVE_CODE_NONE) {
|
|
result->description = _("Script saved successfully.");
|
|
}
|
|
|
|
if (page->is_new) {
|
|
/* notify manager windows of newly created script */
|
|
page->is_new = FALSE;
|
|
sieve_manager_script_created(session,
|
|
page->script_name);
|
|
}
|
|
}
|
|
sieve_editor_update_status(page, result);
|
|
}
|
|
|
|
static void sieve_editor_save(SieveEditorPage *page)
|
|
{
|
|
gchar *text;
|
|
gint len = sieve_editor_get_text(page, &text);
|
|
sieve_editor_set_status(page, _("Saving..."));
|
|
sieve_editor_set_status_icon(page, NULL);
|
|
sieve_session_put_script(page->session, page->script_name, len, text,
|
|
(sieve_session_data_cb_fn)got_data_saved, page);
|
|
g_free(text);
|
|
}
|
|
|
|
static void sieve_editor_save_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
sieve_editor_save(page);
|
|
}
|
|
|
|
static void sieve_editor_find_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
sieve_editor_search(page);
|
|
}
|
|
|
|
static void got_data_checked(SieveSession *session, gboolean abort,
|
|
SieveResult *result, SieveEditorPage *page)
|
|
{
|
|
if (abort)
|
|
return;
|
|
sieve_editor_update_status(page, result);
|
|
}
|
|
|
|
static void sieve_editor_check_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
gchar *text;
|
|
gint len = sieve_editor_get_text(page, &text);
|
|
sieve_editor_set_status(page, _("Checking syntax..."));
|
|
sieve_editor_set_status_icon(page, NULL);
|
|
sieve_session_check_script(page->session, len, text,
|
|
(sieve_session_data_cb_fn)got_data_checked, page);
|
|
g_free(text);
|
|
}
|
|
|
|
static void sieve_editor_changed_cb(GtkTextBuffer *textbuf,
|
|
SieveEditorPage *page)
|
|
{
|
|
if (!page->modified) {
|
|
sieve_editor_set_modified(page, TRUE);
|
|
}
|
|
}
|
|
|
|
static void sieve_editor_destroy(SieveEditorPage *page)
|
|
{
|
|
gtk_widget_destroy(page->window);
|
|
undo_destroy(page->undostruct);
|
|
g_free(page);
|
|
}
|
|
|
|
void sieve_editor_close(SieveEditorPage *page)
|
|
{
|
|
editors = g_slist_remove(editors, (gconstpointer)page);
|
|
sieve_editor_destroy(page);
|
|
sieve_sessions_discard_callbacks(page);
|
|
}
|
|
|
|
static gboolean sieve_editor_confirm_close(SieveEditorPage *page)
|
|
{
|
|
if (page->modified) {
|
|
switch (alertpanel(_("Save changes"),
|
|
_("This script has been modified. Save the latest changes?"),
|
|
_("_Discard"), _("+_Save"), GTK_STOCK_CANCEL)) {
|
|
case G_ALERTDEFAULT:
|
|
return TRUE;
|
|
case G_ALERTALTERNATE:
|
|
page->closing = TRUE;
|
|
sieve_editor_save(page);
|
|
return FALSE;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void sieve_editor_close_cb(GtkAction *action, SieveEditorPage *page)
|
|
{
|
|
if (sieve_editor_confirm_close(page)) {
|
|
sieve_editor_close(page);
|
|
}
|
|
}
|
|
|
|
static gint sieve_editor_delete_cb(GtkWidget *widget, GdkEventAny *event,
|
|
SieveEditorPage *page)
|
|
{
|
|
sieve_editor_close_cb(NULL, page);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* sieve_editor_undo_state_changed:
|
|
*
|
|
* Change the sensivity of the menuentries undo and redo
|
|
**/
|
|
static void sieve_editor_undo_state_changed(UndoMain *undostruct,
|
|
gint undo_state, gint redo_state, gpointer data)
|
|
{
|
|
SieveEditorPage *page = (SieveEditorPage *)data;
|
|
|
|
switch (undo_state) {
|
|
case UNDO_STATE_TRUE:
|
|
if (!undostruct->undo_state) {
|
|
undostruct->undo_state = TRUE;
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Undo", TRUE);
|
|
}
|
|
break;
|
|
case UNDO_STATE_FALSE:
|
|
if (undostruct->undo_state) {
|
|
undostruct->undo_state = FALSE;
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Undo", FALSE);
|
|
}
|
|
break;
|
|
case UNDO_STATE_UNCHANGED:
|
|
break;
|
|
case UNDO_STATE_REFRESH:
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Undo", undostruct->undo_state);
|
|
break;
|
|
default:
|
|
g_warning("Undo state not recognized");
|
|
break;
|
|
}
|
|
|
|
switch (redo_state) {
|
|
case UNDO_STATE_TRUE:
|
|
if (!undostruct->redo_state) {
|
|
undostruct->redo_state = TRUE;
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Redo", TRUE);
|
|
}
|
|
break;
|
|
case UNDO_STATE_FALSE:
|
|
if (undostruct->redo_state) {
|
|
undostruct->redo_state = FALSE;
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Redo", FALSE);
|
|
}
|
|
break;
|
|
case UNDO_STATE_UNCHANGED:
|
|
break;
|
|
case UNDO_STATE_REFRESH:
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Edit/Redo", undostruct->redo_state);
|
|
break;
|
|
default:
|
|
g_warning("Redo state not recognized");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
SieveEditorPage *sieve_editor_new(SieveSession *session, gchar *script_name)
|
|
{
|
|
SieveEditorPage *page;
|
|
GtkUIManager *ui_manager;
|
|
UndoMain *undostruct;
|
|
GtkWidget *window;
|
|
GtkWidget *menubar;
|
|
GtkWidget *vbox, *hbox, *hbox1;
|
|
GtkWidget *scrolledwin;
|
|
GtkWidget *text;
|
|
GtkTextBuffer *buffer;
|
|
GtkWidget *check_btn, *save_btn, *close_btn;
|
|
GtkWidget *status_text;
|
|
GtkWidget *status_icon;
|
|
|
|
page = g_new0(SieveEditorPage, 1);
|
|
|
|
/* window */
|
|
window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "sieveeditor");
|
|
gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
|
|
MANAGE_WINDOW_SIGNALS_CONNECT (window);
|
|
g_signal_connect(G_OBJECT(window), "delete_event",
|
|
G_CALLBACK(sieve_editor_delete_cb), page);
|
|
|
|
vbox = gtk_vbox_new(FALSE, 0);
|
|
gtk_container_add(GTK_CONTAINER(window), vbox);
|
|
|
|
ui_manager = gtk_ui_manager_new();
|
|
cm_menu_create_action_group_full(ui_manager,
|
|
"Menu", sieve_editor_entries, G_N_ELEMENTS(sieve_editor_entries),
|
|
page);
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENUBAR)
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Filter", "Filter", GTK_UI_MANAGER_MENU)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Edit", "Edit", GTK_UI_MANAGER_MENU)
|
|
|
|
/* Filter menu */
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Filter", "Save", "Filter/Save", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Filter", "CheckSyntax", "Filter/CheckSyntax", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Filter", "Revert", "Filter/Revert", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Filter", "Close", "Filter/Close", GTK_UI_MANAGER_MENUITEM)
|
|
|
|
/* Edit menu */
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Undo", "Edit/Undo", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Redo", "Edit/Redo", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Separator1", "Edit/---", GTK_UI_MANAGER_SEPARATOR)
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Cut", "Edit/Cut", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Copy", "Edit/Copy", GTK_UI_MANAGER_MENUITEM)
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Paste", "Edit/Paste", GTK_UI_MANAGER_MENUITEM)
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "SelectAll", "Edit/SelectAll", GTK_UI_MANAGER_MENUITEM)
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Separator2", "Edit/---", GTK_UI_MANAGER_SEPARATOR)
|
|
|
|
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Edit", "Find", "Edit/Find", GTK_UI_MANAGER_MENUITEM)
|
|
|
|
menubar = gtk_ui_manager_get_widget(ui_manager, "/Menu");
|
|
|
|
gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
|
|
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
|
|
|
|
cm_menu_set_sensitive_full(ui_manager, "Menu/Edit/Undo", FALSE);
|
|
cm_menu_set_sensitive_full(ui_manager, "Menu/Edit/Redo", FALSE);
|
|
|
|
/* text */
|
|
scrolledwin = gtk_scrolled_window_new(NULL, NULL);
|
|
gtk_widget_set_size_request (scrolledwin, 660, 408);
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
|
|
GTK_POLICY_AUTOMATIC,
|
|
GTK_POLICY_AUTOMATIC);
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
|
|
GTK_SHADOW_IN);
|
|
gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0);
|
|
|
|
text = gtk_text_view_new();
|
|
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD_CHAR);
|
|
gtk_text_view_set_editable(GTK_TEXT_VIEW(text), TRUE);
|
|
gtk_container_add(GTK_CONTAINER(scrolledwin), text);
|
|
|
|
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
|
|
g_signal_connect(G_OBJECT(buffer), "changed",
|
|
G_CALLBACK(sieve_editor_changed_cb), page);
|
|
|
|
/* set text font */
|
|
if (prefs_common_get_prefs()->textfont) {
|
|
PangoFontDescription *font_desc;
|
|
|
|
font_desc = pango_font_description_from_string
|
|
(prefs_common_get_prefs()->textfont);
|
|
if (font_desc) {
|
|
gtk_widget_modify_font(text, font_desc);
|
|
pango_font_description_free(font_desc);
|
|
}
|
|
}
|
|
|
|
hbox = gtk_hbox_new (FALSE, 8);
|
|
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
|
|
|
|
/* status */
|
|
status_icon = gtk_image_new ();
|
|
gtk_box_pack_start (GTK_BOX (hbox), status_icon, FALSE, FALSE, 0);
|
|
status_text = gtk_label_new ("");
|
|
gtk_box_pack_start (GTK_BOX (hbox), status_text, FALSE, FALSE, 0);
|
|
gtk_label_set_justify (GTK_LABEL (status_text), GTK_JUSTIFY_LEFT);
|
|
|
|
/* buttons */
|
|
gtkut_stock_with_text_button_set_create(&hbox1,
|
|
&close_btn, GTK_STOCK_CANCEL, _("_Close"),
|
|
&check_btn, GTK_STOCK_OK, _("Chec_k Syntax"),
|
|
&save_btn, GTK_STOCK_SAVE, _("_Save"));
|
|
gtk_box_pack_end (GTK_BOX (hbox), hbox1, FALSE, FALSE, 0);
|
|
gtk_widget_grab_default (save_btn);
|
|
g_signal_connect (G_OBJECT (close_btn), "clicked",
|
|
G_CALLBACK (sieve_editor_close_cb), page);
|
|
g_signal_connect (G_OBJECT (check_btn), "clicked",
|
|
G_CALLBACK (sieve_editor_check_cb), page);
|
|
g_signal_connect (G_OBJECT (save_btn), "clicked",
|
|
G_CALLBACK (sieve_editor_save_cb), page);
|
|
|
|
undostruct = undo_init(text);
|
|
undo_set_change_state_func(undostruct, &sieve_editor_undo_state_changed,
|
|
page);
|
|
|
|
page->window = window;
|
|
page->ui_manager = ui_manager;
|
|
page->text = text;
|
|
page->undostruct = undostruct;
|
|
page->session = session;
|
|
page->script_name = script_name;
|
|
page->status_text = status_text;
|
|
page->status_icon = status_icon;
|
|
|
|
editors = g_slist_prepend(editors, page);
|
|
|
|
sieve_editor_set_modified(page, FALSE);
|
|
|
|
return page;
|
|
}
|
|
|
|
SieveEditorPage *sieve_editor_get(SieveSession *session, gchar *script_name)
|
|
{
|
|
GSList *item;
|
|
SieveEditorPage *page;
|
|
for (item = editors; item; item = item->next) {
|
|
page = (SieveEditorPage *)item->data;
|
|
if (page->session == session &&
|
|
strcmp(script_name, page->script_name) == 0)
|
|
return page;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void sieve_editor_present(SieveEditorPage *page)
|
|
{
|
|
gtk_window_present(GTK_WINDOW(page->window));
|
|
}
|
|
|
|
void sieve_editor_show(SieveEditorPage *page)
|
|
{
|
|
gtk_widget_show_all(GTK_WIDGET(page->window));
|
|
}
|
|
|
|
static void sieve_editor_set_modified(SieveEditorPage *page,
|
|
gboolean modified)
|
|
{
|
|
gchar *title;
|
|
|
|
page->modified = modified;
|
|
cm_menu_set_sensitive_full(page->ui_manager, "Menu/Filter/Revert",
|
|
modified);
|
|
|
|
title = g_strdup_printf(_("%s - Sieve Filter%s"), page->script_name,
|
|
modified ? _(" [Edited]") : "");
|
|
gtk_window_set_title (GTK_WINDOW (page->window), title);
|
|
g_free(title);
|
|
|
|
if (modified) {
|
|
sieve_editor_set_status(page, "");
|
|
sieve_editor_set_status_icon(page, NULL);
|
|
}
|
|
}
|
|
|
|
static void got_data_loading(SieveSession *session, gboolean aborted,
|
|
gchar *contents, SieveEditorPage *page)
|
|
{
|
|
if (aborted)
|
|
return;
|
|
if (contents == NULL) {
|
|
/* end of data */
|
|
sieve_editor_set_status(page, "");
|
|
return;
|
|
}
|
|
if (contents == (void *)-1) {
|
|
/* error */
|
|
if (page->first_line) {
|
|
/* no data. show error in manager window */
|
|
if (page->on_load_error)
|
|
page->on_load_error(session, page->on_load_error_data);
|
|
} else {
|
|
/* partial failure. show error in editor window */
|
|
sieve_editor_set_status(page, _("Unable to get script contents"));
|
|
sieve_editor_set_status_icon(page, GTK_STOCK_DIALOG_ERROR);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (page->first_line) {
|
|
page->first_line = FALSE;
|
|
sieve_editor_show(page);
|
|
} else {
|
|
sieve_editor_append_text(page, "\n", 1);
|
|
}
|
|
sieve_editor_append_text(page, contents, strlen(contents));
|
|
}
|
|
|
|
/* load the script for this editor */
|
|
void sieve_editor_load(SieveEditorPage *page,
|
|
sieve_session_cb_fn on_load_error, gpointer load_error_data)
|
|
{
|
|
page->first_line = TRUE;
|
|
page->on_load_error = on_load_error;
|
|
page->on_load_error_data = load_error_data;
|
|
sieve_editor_set_status(page, _("Loading..."));
|
|
sieve_editor_set_status_icon(page, NULL);
|
|
sieve_session_get_script(page->session, page->script_name,
|
|
(sieve_session_data_cb_fn)got_data_loading, page);
|
|
}
|