/* * grn_msgpost.c * * $Id: grn_msgpost.c,v 1.27 2000/07/19 06:26:21 sc Exp $ */ /* Copyright (C) 1999-2000 Sergey Chernikov (sc@ivvs.ul.ru) * * Authors: Sergey Chernikov * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ #include #include #include "grn_consts.h" #include #include "grn_msgpost.h" #include "grn_util.h" #include "grn_config.h" #include "grn_msgwin.h" #include "grn_misc.h" #include "grn_menu.h" #include "grn_vars.h" #include "queue.h" #include "grn_perl.h" #include "grn_nglist.h" #include "grn_mhdrwin.h" void msgpost_widget_refresh(GtkWidget *mpw, t_message *msg); static GSList *newsgroups2list(gchar *src) { gchar **arr = g_strsplit(src, ",", 0); gint i = 0; GSList *ret = NULL; while (arr[i]) ret = g_slist_prepend(ret, g_strstrip(g_strdup(arr[i++]))); ret = g_slist_reverse(ret); g_strfreev(arr); return ret; } static gchar *ne_groups(gchar *groups) { GSList *gl, *l; GList *ng; gchar *ret = NULL; gl = newsgroups2list(groups); for (l=gl; l; l=l->next) { gchar *group = (gchar *) l->data; gboolean found = FALSE; for (ng = GRN->ng_list; ng; ng=ng->next) { grn_newsgroup *grp = (grn_newsgroup *) ng->data; if ((! grp) || (! str_check(grp->name))) continue; if (! strcmp(grp->name, group)) { found = TRUE; break; } } if (! found) { if (! str_check(ret)) ret = g_strdup(group); else { str_add(&ret, ", "); str_add(&ret, group); } } str_free(&group); } g_slist_free(gl); return ret; } static void msg_check_body(t_message *msg, GSList **l) { msg_check_res *mcr = NULL; gchar **lines = NULL; gint i, nlines=0, nqlines=0; regex_t regex; regmatch_t regmatch; if (! str_check(msg->body)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("Message body is empty")); mcr->gl = WARN; *l = g_slist_append(*l, mcr); return; } if (! strchr(msg->body, '\n')) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("No linefeeds in the body")); mcr->gl = WARN; *l = g_slist_append(*l, mcr); } lines = g_strsplit(msg->body, "\n", -1); if (! regcomp(®ex, grn_prefs.re_quoting, REG_EXTENDED|REG_NOSUB)) { for (i=0; lines[i]; i++) { nlines++; if (! regexec(®ex, lines[i], 0, ®match, 0)) nqlines++; } regfree(®ex); } if ((nlines > 0) && (((gfloat) nqlines / (gfloat) nlines) > 0.75)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("The body has more than 75% of quoting")); mcr->gl = WARN; *l = g_slist_append(*l, mcr); } g_strfreev(lines); } static GSList *msg_check(t_message *msg) { GSList *ret = NULL; msg_check_res *mcr = NULL; if (! str_check(msg->mh->from)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("'From' field is empty")); mcr->gl = BAD; ret = g_slist_append(ret, mcr); } if (! str_check(msg->mh->newsgroups)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("No newsgroups specified")); mcr->gl = BAD; ret = g_slist_append(ret, mcr); } else { gchar *igroups = ne_groups(msg->mh->newsgroups); if (str_check(igroups)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup_printf(_("Invalid group[s]: %s"), igroups); mcr->gl = BAD; ret = g_slist_append(ret, mcr); } } if (! str_check(msg->mh->subject)) { mcr = g_new(msg_check_res, 1); mcr->result = g_strdup(_("Subject is empty")); mcr->gl = WARN; ret = g_slist_append(ret, mcr); } msg_check_body(msg, &ret); return ret; } msg_goodness get_goodness(GSList *gl) { GSList *l; msg_goodness ret = OKAY; for (l=gl; l; l=l->next) { msg_check_res *mcr = (msg_check_res *) l->data; if (! mcr) continue; if (mcr->gl == BAD) return BAD; ret = mcr->gl; } return ret; } gchar *goodness_list_to_str(GSList *gl, msg_goodness mg) { GSList *l; gchar *ret = NULL; for (l=gl; l; l=l->next) { msg_check_res *mcr = (msg_check_res *) l->data; if (! mcr) continue; if (mcr->gl == mg) { str_add(&ret, " - "); str_add(&ret, mcr->result); str_add(&ret, "\n"); } } return ret; } void goodness_list_free(GSList *gl) { GSList *l; for (l=gl; l; l=l->next) { msg_check_res *mcr = (msg_check_res *) l->data; if (! mcr) continue; str_free(&(mcr->result)); g_free(mcr); } g_slist_free(gl); } gchar *trimmed_refs(const gchar *refs) { const gint gnksa_cutoff = 998 - (gint) strlen("References: "); gint len, i, n=0, k=0; gchar **ref_arr; gchar *ret = NULL; g_return_val_if_fail(refs != NULL, NULL); len = strlen(refs); if (len <= gnksa_cutoff) return g_strdup(refs); ref_arr = g_strsplit(refs, ">", -1); for (i=0; ref_arr[i]; i++) n++; len = 0; for (i=n-1; i>=0; i--) { gchar *s1, *s = ref_arr[i]; gchar *p = strchr(s, '<'); gint l1; if (p) *p = ' '; g_strstrip(s); if (strlen(s) <= 0) continue; s1 = g_strdup_printf("<%s>", s); l1 = strlen(s1); str_free(&s1); len += l1 + 1; if (len > gnksa_cutoff) { k = i+1; break; } } for (i=k; ref_arr[i]; i++) { gchar *s1, *s = ref_arr[i]; gchar *p = strchr(s, '<'); if (p) *p = ' '; g_strstrip(s); if (strlen(s) <= 0) continue; s1 = g_strdup_printf("<%s>", s); if (str_check(ret)) { str_add(&ret, " "); str_add(&ret, s1); str_free(&s1); } else ret = s1; } g_strfreev(ref_arr); return ret; } static void add_hdr(gchar **dst, gchar *hdrname, gchar *hdr) { str_add(dst, hdrname); str_add(dst, hdr); str_add(dst, "\n"); } static void extra_hdrs_add(gchar *key, gchar *data, gchar **ret) { if (str_check(data)) { gchar *buf = g_strdup_printf("%s: %s\n", key, data); str_add(ret, buf); str_free(&buf); } } gchar *msg_to_text(t_message *msg) { gchar *ret = NULL; if (! str_check(msg->mh->subject)) msg->mh->subject = g_strdup(_("")); ret = g_strconcat("From: ", msg->mh->from, "\n", "Path: ", msg->mh->path, "\n", "Newsgroups: ", msg->mh->newsgroups, "\n", "Subject: ", msg->mh->subject, "\n", NULL); if (str_check(msg->mh->date)) add_hdr(&ret, "Date: ", msg->mh->date); if (str_check(msg->mh->id)) add_hdr(&ret, "Message-ID: ", msg->mh->id); if (str_check(msg->mh->ref)) { gchar *p = msg->mh->ref; msg->mh->ref = trimmed_refs(p); str_free(&p); add_hdr(&ret, "References: ", msg->mh->ref); } if (msg->mh->extra_hdrs) g_hash_table_foreach(msg->mh->extra_hdrs, (GHFunc) extra_hdrs_add, &ret); str_add(&ret, "\n"); str_add(&ret, msg->body); return ret; } static void fill_msg_headers(t_message *msg) { gchar *tmp = NULL; g_return_if_fail(msg != NULL); if (! msg->mh) msg->mh = t_msgheaders_alloc(); str_free(&(msg->mh->id)); str_free(&(msg->mh->ref)); str_free(&(msg->mh->date)); str_free(&(msg->mh->path)); t_msgheaders_rm_extra_hdrs(msg->mh); str_free(&(msg->mh->from)); msg->mh->from = g_strdup(grn_prefs.name); if (grn_prefs.email) tmp = g_strdup_printf(" <%s>", grn_prefs.email); if (tmp) str_add(&(msg->mh->from), tmp); str_free(&tmp); tmp = g_strconcat(get_host_name(), "!", g_get_user_name(), NULL); str_add(&(msg->mh->path), tmp); str_free(&tmp); if (str_check(grn_prefs.ua)) { tmp = g_strdup(grn_prefs.ua); grn_subst_vars(&tmp); t_msgheaders_add_extra_hdr(msg->mh, "User-Agent", tmp); str_free(&tmp); } if (str_check(grn_prefs.org)) { tmp = g_strdup(grn_prefs.org); grn_subst_vars(&tmp); t_msgheaders_add_extra_hdr(msg->mh, "Organization", tmp); str_free(&tmp); } if (str_check(grn_prefs.replyto)) t_msgheaders_add_extra_hdr(msg->mh, "Reply-To", grn_prefs.replyto); } gchar *create_forward(t_message *m) { gchar *ret = NULL; gchar *s = NULL, *s1 = NULL; g_return_val_if_fail(m != NULL, NULL); g_return_val_if_fail(m->mh != NULL, NULL); ret = g_strdup("\n\n"); s = g_strnfill(63, '='); str_add(&ret, s); str_free(&s); str_add(&ret, "\n"); if (str_check(m->mh->newsgroups)) { s = g_strdup_printf("Newsgroups: %s\n", m->mh->newsgroups); str_add(&ret, s); str_free(&s); } else if (m->mh->grp) { s = NULL; if (m->mh->grp->name) { if (m->mh->grp->descr) s = g_strdup_printf("Newsgroup: %s (%s)\n", m->mh->grp->name, m->mh->grp->descr); else s = g_strdup_printf("Newsgroup: %s\n", m->mh->grp->name); } if (s) str_add(&ret, s); str_free(&s); } if (str_check(m->mh->from)) { s = g_strdup_printf("From: %s\n", m->mh->from); str_add(&ret, s); str_free(&s); } s1 = t_msgheaders_get_extra_hdr(m->mh, "X-Comment-To"); if (str_check(s1)) { s = g_strdup_printf("To: %s\n", s1); str_add(&ret, s); str_free(&s); } if (str_check(m->mh->subject)) { s = g_strdup_printf("Subject: %s\n", m->mh->subject); str_add(&ret, s); str_free(&s); } s = g_strnfill(63, '='); str_add(&ret, s); str_free(&s); str_add(&ret, "\n"); if (str_check(m->body)) str_add(&ret, m->body); return ret; } gchar *create_quoting(t_message *m) { gchar **lines, *ret = NULL; gint i; g_return_val_if_fail(m != NULL, NULL); lines = g_strsplit(m->body, "\n", -1); for (i=0; lines[i]; i++) { gchar *s = g_strdup_printf("%c %s\n", '>', lines[i]); str_add(&ret, s); str_free(&s); } g_strfreev(lines); return ret; } static void subject_changed(GtkWidget *w, GtkWidget *p) { gchar *subj, *title; GtkWidget *wnd = gtk_object_get_data(GTK_OBJECT(p), KEY_WND); if (! wnd) return; subj = gtk_entry_get_text(GTK_ENTRY(w)); title = g_strdup_printf("%s: %s", _("GRN post article"), subj); gtk_window_set_title(GTK_WINDOW(wnd), title); g_free(title); } static GtkWidget *create_msgpost_pane(GtkWidget *parent) { GtkWidget *table, *label, *entry; table = gtk_table_new(2, 2, FALSE); label = gtk_label_new(_("From:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL, GTK_FILL, 3,1); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1,3,0,1, GTK_EXPAND|GTK_FILL, GTK_FILL, 0,1); gtk_object_set_data(GTK_OBJECT(parent), KEY_MW_FROM, entry); label = gtk_label_new(_("Newsgroups:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL, GTK_FILL, 3,1); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1,2,1,2, GTK_EXPAND|GTK_FILL, GTK_FILL, 0,1); gtk_object_set_data(GTK_OBJECT(parent), KEY_MW_NEWSGROUPS, entry); label = gtk_label_new(_("Subject:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL, GTK_FILL, 3,1); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1,3,2,3, GTK_EXPAND|GTK_FILL, GTK_FILL, 0,1); gtk_object_set_data(GTK_OBJECT(parent), KEY_MW_SUBJ, entry); gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(subject_changed), parent); return table; } static void abort_cb(gint reply, GtkWidget *w) { g_return_if_fail(w != NULL); if (reply == GNOME_YES) gtk_widget_destroy(w); } static gboolean delete_wnd(GtkWidget *w) { grn_save_ws(2, w); if (grn_prefs.cfms[4]) { gnome_app_question(GNOME_APP(GRN->window), _("Are you sure you wish to abort posting?"), (GnomeReplyCallback) abort_cb, w); return TRUE; } else return FALSE; } static gint evt_msgpost_keypress(GtkWidget *w, GdkEventKey *event, GtkWidget *mpw) { GtkWidget *text = gtk_object_get_data(GTK_OBJECT(mpw), KEY_TXT_BODY); switch (event->keyval) { case GDK_Escape: if (! delete_wnd(w)) gtk_widget_destroy(w); break; case GDK_Return: case GDK_KP_Enter: if (text && (! GTK_WIDGET_HAS_FOCUS(text))) gtk_widget_grab_focus(text); else return FALSE; break; default: return FALSE; } gtk_signal_emit_stop_by_name(GTK_OBJECT(w), "key_press_event"); return TRUE; } void replace_msg(GtkObject *mpw, t_message *msg, const gchar *key) { t_message *m; g_return_if_fail(mpw != NULL); g_return_if_fail(msg != NULL); g_return_if_fail(key != NULL); grn_lock(); m = gtk_object_get_data(mpw, key); if (m) { t_message_free(&m); gtk_object_remove_data(mpw, key); } gtk_object_set_data_full(mpw, key, msg, (GtkDestroyNotify) t_message_destroy); grn_unlock(); } static void text_entered_new(GtkWidget *w) { glong ph_res; t_message *m; gtk_signal_disconnect_by_func(GTK_OBJECT(w), text_entered_new, NULL); if (! GTK_IS_TEXT(w)) return; m = gtk_object_get_data(GTK_OBJECT(w), KEY_MSG); if (! m) return; #ifdef USE_PERL ph_res = perl_hook_run("TemplateNew", GRN, m, NULL); if (ph_res >= 1) { GtkWidget *mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_WND); if (m->pos >= strlen(m->body)) m->pos = strlen(m->body) - 1; if (mpw) msgpost_widget_refresh(mpw, m); else { gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, m->body, strlen(m->body)); gtk_text_set_point(GTK_TEXT(w), m->pos); gtk_editable_set_position(GTK_EDITABLE(w), m->pos); } } #endif } static void text_entered_followup(GtkWidget *w) { glong ph_res = 0; t_message *m, *m1; GtkWidget *mpw; gtk_signal_disconnect_by_func(GTK_OBJECT(w), text_entered_followup, NULL); if (! GTK_IS_TEXT(w)) return; m1 = gtk_object_get_data(GTK_OBJECT(w), KEY_MSG1); m = gtk_object_get_data(GTK_OBJECT(w), KEY_MSG); if (! m) return; #ifdef USE_PERL ph_res = perl_hook_run("TemplateReply", GRN, m, m1); #endif if (ph_res < 1) { m->body = create_quoting(m1); m->pos = 0; } if (m->pos >= strlen(m->body)) m->pos = strlen(m->body) - 1; mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_WND); if (mpw) msgpost_widget_refresh(mpw, m); else { gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, m->body, strlen(m->body)); gtk_text_set_point(GTK_TEXT(w), m->pos); gtk_editable_set_position(GTK_EDITABLE(w), m->pos); } } static void text_entered_forward(GtkWidget *w) { glong ph_res = 0; t_message *m, *m1; GtkWidget *mpw; gtk_signal_disconnect_by_func(GTK_OBJECT(w), text_entered_forward, NULL); if (! GTK_IS_TEXT(w)) return; m1 = gtk_object_get_data(GTK_OBJECT(w), KEY_MSG1); m = gtk_object_get_data(GTK_OBJECT(w), KEY_MSG); if (! m) return; #ifdef USE_PERL ph_res = perl_hook_run("TemplateForward", GRN, m, m1); #endif if (ph_res < 1) { m->body = create_forward(m1); m->pos = 0; } if (m->pos >= strlen(m->body)) m->pos = strlen(m->body) - 1; mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_WND); if (mpw) msgpost_widget_refresh(mpw, m); else { gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, m->body, strlen(m->body)); gtk_text_set_point(GTK_TEXT(w), m->pos); gtk_editable_set_position(GTK_EDITABLE(w), m->pos); } } static void mpw_focus(GtkWindow *wnd, gpointer data) { GRN->focused = wnd; } static void mpw_destroy(GtkWidget *wnd, gpointer data) { GRN->focused = NULL; } GtkWidget *create_msgpost_widget(msg_create_mode mcm) { GtkWidget *vbox, *wnd, *text, *bar, *table, *cntr; GnomeDockItem *item; GtkAdjustment *adj; GtkSignalFunc text_entered_func = NULL; grn_lock(); vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), create_msgpost_pane(vbox), FALSE, FALSE, 0); table = gtk_table_new(2, 1, FALSE); gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); adj = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 0, 0, 0)); text = gtk_text_new(NULL, adj); gtk_text_set_editable(GTK_TEXT(text), TRUE); gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); gtk_table_attach(GTK_TABLE(table), text, 0,1,0,1, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0,0); gtk_object_set_data(GTK_OBJECT(vbox), KEY_TXT_BODY, text); gtk_table_attach(GTK_TABLE(table), gtk_vscrollbar_new(adj), 1,2,0,1, GTK_FILL, GTK_FILL, 0,0); wnd = gnome_app_new("GRN_post", _("GRN post article")); gtk_object_set_data(GTK_OBJECT(vbox), KEY_WND, wnd); gtk_object_set_data(GTK_OBJECT(wnd), KEY_MSGPOST, vbox); gtk_window_set_default_size(GTK_WINDOW(wnd), grn_prefs.ws[2].width, grn_prefs.ws[2].height); gtk_widget_set_uposition(GTK_WIDGET(wnd), grn_prefs.ws[2].x, grn_prefs.ws[2].y); cntr = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(cntr), GTK_SHADOW_ETCHED_OUT); gtk_container_add(GTK_CONTAINER(cntr), vbox); gtk_widget_show(cntr); gnome_app_set_contents(GNOME_APP(wnd), cntr); gnome_app_create_menus(GNOME_APP(wnd), msgpost_menu); gnome_app_create_toolbar(GNOME_APP(wnd), msgpost_toolbar); item = gnome_app_get_dock_item_by_name(GNOME_APP(wnd), GNOME_APP_TOOLBAR_NAME); if (item) { bar = gnome_dock_item_get_child(item); if (bar) { gtk_toolbar_set_style(GTK_TOOLBAR(bar), grn_get_toolbar_style()); gtk_object_set_data(GTK_OBJECT(bar), KEY_MSGPOST, vbox); } } item = gnome_app_get_dock_item_by_name(GNOME_APP(wnd), GNOME_APP_MENUBAR_NAME); if (item) { bar = gnome_dock_item_get_child(item); if (bar) { gchar *s1 = _("Article"); grn_menu_set_data(bar, s1, _("Post"), KEY_MSGPOST, vbox); grn_menu_set_data(bar, s1, _("Cancel"), KEY_MSGPOST, vbox); grn_menu_set_data(bar, s1, _("Newsgroups"), KEY_MSGPOST, vbox); grn_menu_set_data(bar, s1, _("Edit headers"), KEY_MSGPOST, vbox); grn_menu_set_data(bar, s1, _("Attachments..."), KEY_MSGPOST, vbox); s1 = _("File"); grn_menu_set_data(bar, s1, _("Load..."), KEY_MSGPOST, vbox); } } switch (mcm) { case MSG_CREATE_FOLLOWUP: text_entered_func = GTK_SIGNAL_FUNC(text_entered_followup); break; case MSG_CREATE_FORWARD: text_entered_func = GTK_SIGNAL_FUNC(text_entered_forward); break; default: text_entered_func = GTK_SIGNAL_FUNC(text_entered_new); } gtk_signal_connect(GTK_OBJECT(wnd), "delete_event", GTK_SIGNAL_FUNC(delete_wnd), NULL); gtk_signal_connect(GTK_OBJECT(wnd), "key_press_event", GTK_SIGNAL_FUNC(evt_msgpost_keypress), vbox); gtk_signal_connect(GTK_OBJECT(wnd), "focus_in_event", GTK_SIGNAL_FUNC(mpw_focus), NULL); gtk_signal_connect(GTK_OBJECT(wnd), "destroy", GTK_SIGNAL_FUNC(mpw_destroy), NULL); if (text_entered_func) gtk_signal_connect(GTK_OBJECT(text), "focus_in_event", text_entered_func, NULL); gtk_widget_show_all(wnd); grn_unlock(); build_macros_menu(GNOME_APP(wnd)->menubar, 3); return vbox; } static void entry_left(GtkWidget *entry, GdkEventFocus *e, gchar **text) { gchar *en_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); str_free(text); *text = en_text; } static void subject_left(GtkWidget *entry, GdkEventFocus *e, t_msgheaders *mh) { gchar *en_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); str_free(&(mh->subject)); mh->subject = en_text; } static GtkWidget *msgpost_set_hdr(GtkWidget *mw, gchar *id, gchar **text, gboolean set_signal) { GtkWidget *hw; g_return_val_if_fail(mw != NULL, NULL); g_return_val_if_fail(id != NULL, NULL); if (! text) return NULL; grn_lock(); hw = gtk_object_get_data(GTK_OBJECT(mw), id); grn_unlock(); if (! hw) return NULL; grn_widget_set_style(hw, grn_prefs.fonts[2], NULL, NULL, NULL); grn_lock(); if (GTK_IS_ENTRY(hw)) { if (*text) { gtk_entry_set_text(GTK_ENTRY(hw), *text); if (set_signal) gtk_signal_connect(GTK_OBJECT(hw), "focus_out_event", GTK_SIGNAL_FUNC(entry_left), text); } else gtk_entry_set_text(GTK_ENTRY(hw), ""); } else if (GTK_IS_LABEL(hw)) { if (*text) gtk_label_set_text(GTK_LABEL(hw), *text); else gtk_label_set_text(GTK_LABEL(hw), ""); } grn_unlock(); return hw; } void msgpost_widget_refresh(GtkWidget *mpw, t_message *msg) { GtkText *text; g_return_if_fail(mpw != NULL); g_return_if_fail(msg != NULL); msgpost_set_hdr(mpw, KEY_MW_FROM, &(msg->mh->from), FALSE); msgpost_set_hdr(mpw, KEY_MW_NEWSGROUPS, &(msg->mh->newsgroups), FALSE); msgpost_set_hdr(mpw, KEY_MW_SUBJ, &(msg->mh->subject), FALSE); grn_lock(); text = GTK_TEXT(gtk_object_get_data(GTK_OBJECT(mpw), KEY_TXT_BODY)); if (text) { if (str_check(msg->body)) { gtk_text_insert(text, NULL, NULL, NULL, msg->body, strlen(msg->body)); gtk_text_set_point(text, msg->pos); gtk_editable_set_position(GTK_EDITABLE(text), msg->pos); } } grn_unlock(); } void msgpost_widget_set_data(GtkWidget *mpw, t_message *msg, t_message *msg1) { GtkText *text; GtkWidget *w; g_return_if_fail(mpw != NULL); g_return_if_fail(msg != NULL); replace_msg(GTK_OBJECT(mpw), msg, KEY_MSG); msgpost_set_hdr(mpw, KEY_MW_FROM, &(msg->mh->from), TRUE); msgpost_set_hdr(mpw, KEY_MW_NEWSGROUPS, &(msg->mh->newsgroups), TRUE); w = msgpost_set_hdr(mpw, KEY_MW_SUBJ, &(msg->mh->subject), TRUE); if (! msg->mh->subject) gtk_signal_connect(GTK_OBJECT(w), "focus_out_event", GTK_SIGNAL_FUNC(subject_left), msg->mh); grn_lock(); text = GTK_TEXT(gtk_object_get_data(GTK_OBJECT(mpw), KEY_TXT_BODY)); if (text) { gchar *fnt_name; if (grn_prefs.mw_prop) fnt_name = grn_prefs.fonts[0]; else fnt_name = grn_prefs.fonts[1]; grn_widget_set_style(GTK_WIDGET(text), fnt_name, &(grn_prefs.fg_colors[0]), &(grn_prefs.bg_colors[0]), grn_prefs.pixmaps[0]); if (str_check(msg->body)) { gtk_text_insert(text, NULL, NULL, NULL, msg->body, strlen(msg->body)); gtk_text_set_point(text, msg->pos); gtk_editable_set_position(GTK_EDITABLE(text), msg->pos); } gtk_object_set_data(GTK_OBJECT(text), KEY_MSG, msg); if (msg1) { grn_unlock(); replace_msg(GTK_OBJECT(text), msg1, KEY_MSG1); grn_lock(); } gtk_object_set_data(GTK_OBJECT(text), KEY_WND, mpw); } w = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MW_SUBJ); if (w) gtk_widget_grab_focus(w); grn_unlock(); } static t_message *msgpost_get_message(GtkWidget *mpw) { t_message *m = NULL; GtkWidget *w; if (! mpw) return NULL; m = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MSG); if (! m) { m = t_message_alloc(); m->mh = t_msgheaders_alloc(); gtk_object_set_data_full(GTK_OBJECT(mpw), KEY_MSG, m, (GtkDestroyNotify) t_message_destroy); } w = gtk_object_get_data(GTK_OBJECT(mpw), KEY_TXT_BODY); if (w) { str_free(&(m->body)); m->body = g_strdup(gtk_editable_get_chars(GTK_EDITABLE(w), 0, -1)); } w = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MW_FROM); if (w) { str_free(&(m->mh->from)); m->mh->from = g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); } w = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MW_NEWSGROUPS); if (w) { str_free(&(m->mh->newsgroups)); m->mh->newsgroups = g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); } w = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MW_SUBJ); if (w) { str_free(&(m->mh->subject)); m->mh->subject = g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); } return m; } void evt_post_new(GtkWidget *w) { t_message *m; GtkWidget *mpw; g_return_if_fail(w != NULL); if (! GRN->srv.posting) { grn_error(NULL, _("Posting disabled by the server")); return; } m = t_message_alloc(); m->mh = t_msgheaders_alloc(); m->mh->newsgroups = get_cur_group(w); fill_msg_headers(m); mpw = create_msgpost_widget(MSG_CREATE_NEW); msgpost_widget_set_data(mpw, m, NULL); } void evt_post_followup(GtkWidget *w) { t_message *m, *m1; GtkWidget *mpw; g_return_if_fail(w != NULL); if (! GRN->srv.posting) { grn_error(NULL, _("Posting disabled by the server")); return; } m = t_message_alloc(); m->mh = t_msgheaders_alloc(); m1 = get_cur_msg(w); m->mh->newsgroups = get_cur_group(w); fill_msg_headers(m); m->mh->subject = g_strdup(m1->mh->subject); if (m1->mh->ref) m->mh->ref = g_strconcat(m1->mh->ref, " ", NULL); str_add(&(m->mh->ref), m1->mh->id); mpw = create_msgpost_widget(MSG_CREATE_FOLLOWUP); msgpost_widget_set_data(mpw, m, m1); } void evt_post_forward(GtkWidget *w) { t_message *m, *m1; GtkWidget *mpw; g_return_if_fail(w != NULL); if (! GRN->srv.posting) { grn_error(NULL, _("Posting disabled by the server")); return; } m = t_message_alloc(); m->mh = t_msgheaders_alloc(); m1 = get_cur_msg(w); m->mh->newsgroups = get_cur_group(w); fill_msg_headers(m); m->mh->subject = g_strdup(m1->mh->subject); mpw = create_msgpost_widget(MSG_CREATE_FORWARD); msgpost_widget_set_data(mpw, m, m1); } typedef struct sg_data { GtkWidget **dlg; GtkWidget *btn; t_message *m; } sg_data; static void sg_ok(GtkWidget *w, sg_data *sgd) { GtkWidget *gs, *clist, *en; GList *l; gchar *s = NULL; if ((! sgd->m) || (! sgd->m->mh)) return; en = gtk_object_get_data(GTK_OBJECT(*(sgd->dlg)), KEY_MW_NEWSGROUPS); if (! en) return; gs = gtk_object_get_data(GTK_OBJECT(*(sgd->dlg)), KEY_GROUPSEL); if (! gs) return; clist = gtk_object_get_data(GTK_OBJECT(gs), KEY_CL_GROUPS); if (! clist) return; for (l=GTK_CLIST(clist)->selection; l; l=l->next) { gint row = GPOINTER_TO_INT(l->data); gchar *text; gtk_clist_get_text(GTK_CLIST(clist), row, 3, &text); if (s) str_add(&s, ","); str_add(&s, text); } str_free(&(sgd->m->mh->newsgroups)); if (s) { gtk_entry_set_text(GTK_ENTRY(en), s); sgd->m->mh->newsgroups = g_strdup(s); str_free(&s); } else gtk_entry_set_text(GTK_ENTRY(en), ""); } static void sg_destroy(GtkWidget *w, sg_data *sgd) { *(sgd->dlg) = NULL; gtk_widget_set_sensitive(sgd->btn, TRUE); g_free(sgd); } void evt_sel_groups(GtkWidget *w) { GtkWidget *mpw, *en; static GtkWidget *dlg = NULL; GSList *ngl, *l; sg_data *sgd; if (! w->parent) return; if (dlg) return; mpw = gtk_object_get_data(GTK_OBJECT(w->parent), KEY_MSGPOST); if (! mpw) mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGPOST); if (! mpw) return; en = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MW_NEWSGROUPS); if (! en) return; ngl = newsgroups2list(gtk_entry_get_text(GTK_ENTRY(en))); dlg = groupsel_dlg_create(ngl); for (l=ngl; l; l=l->next) g_free(l->data); g_slist_free(ngl); gtk_widget_set_sensitive(w, FALSE); sgd = g_new(sg_data, 1); sgd->dlg = &dlg; sgd->btn = w; sgd->m = msgpost_get_message(mpw); gtk_object_set_data(GTK_OBJECT(dlg), KEY_MW_NEWSGROUPS, en); gnome_dialog_button_connect(GNOME_DIALOG(dlg), 1, GTK_SIGNAL_FUNC(sg_ok), sgd); gtk_signal_connect(GTK_OBJECT(dlg), "destroy", GTK_SIGNAL_FUNC(sg_destroy), sgd); } typedef struct mhe_data { GtkWidget **dlg; GtkWidget *btn; } mhe_data; static void mhe_destroy(GtkWidget *w, mhe_data *mhd) { *(mhd->dlg) = NULL; gtk_widget_set_sensitive(mhd->btn, TRUE); g_free(mhd); } void evt_mhdredit_dlg_create(GtkWidget *w) { GtkWidget *mpw; static GtkWidget *dlg = NULL; t_message *m; mhe_data *mhd; if (! w->parent) return; if (dlg) return; mpw = gtk_object_get_data(GTK_OBJECT(w->parent), KEY_MSGPOST); if (! mpw) mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGPOST); if (! mpw) return; m = gtk_object_get_data(GTK_OBJECT(mpw), KEY_MSG); if (! m) return; dlg = mhdredit_dlg_create(m->mh); gtk_widget_set_sensitive(w, FALSE); mhd = g_new(mhe_data, 1); mhd->dlg = &dlg; mhd->btn = w; gtk_signal_connect(GTK_OBJECT(dlg), "destroy", GTK_SIGNAL_FUNC(mhe_destroy), mhd); } typedef struct post_data { t_message *m; GtkWidget *wnd; } post_data; static void warn_cb(gint reply, post_data *pd) { g_return_if_fail(pd != NULL); if (reply == GNOME_YES) { #ifdef USE_PERL perl_hook_run("PrePost", GRN, pd->m, NULL); #endif if (pd->m) grnq_add_post_article(pd->m); if (pd->wnd) gtk_widget_destroy(pd->wnd); } else t_message_free(&(pd->m)); g_free(pd); } void evt_post_ok(GtkWidget *w) { GtkWidget *mpw, *wnd; t_message *m; GSList *gl; msg_goodness mg; if (flags.post_article) return; if (! w->parent) return; mpw = gtk_object_get_data(GTK_OBJECT(w->parent), KEY_MSGPOST); if (! mpw) mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGPOST); if (! mpw) return; m = t_message_copy(msgpost_get_message(mpw)); wnd = gtk_object_get_data(GTK_OBJECT(mpw), KEY_WND); gl = msg_check(m); mg = get_goodness(gl); if (mg == BAD) { gchar *text1 = goodness_list_to_str(gl, BAD); gchar *text2 = goodness_list_to_str(gl, WARN); gchar *text = g_strdup(_("Posting abandoned!\n\n")); if (str_check(text1)) { str_add(&text, _("Errors:\n")); str_add(&text, text1); str_free(&text1); } if (str_check(text2)) { str_add(&text, _("Warnings:\n")); str_add(&text, text2); str_free(&text2); } grn_error(NULL, text); str_free(&text); goodness_list_free(gl); t_message_free(&m); return; } if (grn_prefs.cfms[5]) { if (mg == WARN) { gchar *text1 = goodness_list_to_str(gl, WARN); gchar *text = g_strdup(_("Some warnings encountered:\n")); post_data *pd = g_new(post_data, 1); str_add(&text, text1); str_free(&text1); str_add(&text, _("\nDo you wish to continue posting?")); pd->m = m; pd->wnd = wnd; gnome_app_question(GNOME_APP(GRN->window), text, (GnomeReplyCallback) warn_cb, pd); str_free(&text); goodness_list_free(gl); return; } } goodness_list_free(gl); #ifdef USE_PERL perl_hook_run("PrePost", GRN, m, NULL); #endif if (m) grnq_add_post_article(m); if (wnd) gtk_widget_destroy(wnd); } void evt_post_cancel(GtkWidget *w) { GtkWidget *mpw, *wnd; if (! w->parent) return; mpw = gtk_object_get_data(GTK_OBJECT(w->parent), KEY_MSGPOST); if (! mpw) mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGPOST); if (! mpw) return; wnd = gtk_object_get_data(GTK_OBJECT(mpw), KEY_WND); if (wnd) { if (grn_prefs.cfms[4]) gnome_app_question(GNOME_APP(GRN->window), _("Are you sure you wish to abort posting?"), (GnomeReplyCallback) abort_cb, wnd); else gtk_widget_destroy(wnd); } } static void load_file_ok(GtkWidget *w, GtkFileSelection *fs) { FILE *f; GtkText *text; gchar *fn = gtk_file_selection_get_filename(fs); f = fopen(fn, "r"); if (f) { gchar *s = g_malloc(8192); text = gtk_object_get_data(GTK_OBJECT(fs), KEY_TXT_BODY); if (text) { gtk_text_freeze(text); while (! feof(f)) { s[0] = '\0'; fgets(s, 8190, f); gtk_text_insert(text, NULL, NULL, NULL, s, strlen(s)); } gtk_text_thaw(text); str_free(&s); } else g_warning("load_file_ok(): internal error"); fclose(f); } else grn_error(fn, _("Can't open file")); gtk_widget_destroy(GTK_WIDGET(fs)); } static void load_file_cancel(GtkWidget *w, GtkFileSelection *fs) { gtk_widget_destroy(GTK_WIDGET(fs)); } void evt_compose_load_file(GtkWidget *w) { GtkWidget *mpw, *fs, *text; if (! w->parent) return; mpw = gtk_object_get_data(GTK_OBJECT(w->parent), KEY_MSGPOST); if (! mpw) mpw = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGPOST); if (! mpw) return; text = gtk_object_get_data(GTK_OBJECT(mpw), KEY_TXT_BODY); if (! text) return; fs = gtk_file_selection_new(_("Load file")); gtk_object_set_data(GTK_OBJECT(fs), KEY_TXT_BODY, text); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), "clicked", GTK_SIGNAL_FUNC(load_file_ok), fs); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->cancel_button), "clicked", GTK_SIGNAL_FUNC(load_file_cancel), NULL); gtk_widget_show(fs); }