Ejemplo n.º 1
0
/* compose_attach */
int compose_attach(Compose * compose, char const * filename)
{
	const int iconsize = 48;
	GtkIconTheme * theme;
	char const * type;
	GdkPixbuf * pixbuf;
	GtkTreeIter iter;
	char * p;
	FILE * fp;

	if(filename == NULL)
		return compose_attach_dialog(compose);
	if((fp = fopen(filename, "rb")) == NULL)
		return -compose_error(compose, strerror(errno), 1);
	if((p = strdup(filename)) == NULL)
	{
		fclose(fp);
		return -compose_error(compose, strerror(errno), 1);
	}
	compose_set_modified(compose, TRUE);
	theme = gtk_icon_theme_get_default();
	pixbuf = NULL;
	if((type = mime_type(compose->mime, filename)) != NULL)
		mime_icons(compose->mime, type, iconsize, &pixbuf, -1);
	if(pixbuf == NULL)
		pixbuf = gtk_icon_theme_load_icon(theme, GTK_STOCK_FILE,
				iconsize, 0, NULL);
	gtk_list_store_append(compose->a_store, &iter);
	gtk_list_store_set(compose->a_store, &iter, CAC_FILENAME, filename,
			CAC_BASENAME, basename(p), CAC_ICON, pixbuf,
			CAC_FILE_POINTER, fp, -1);
	g_object_unref(pixbuf);
	free(p);
	return 0;
}
Ejemplo n.º 2
0
/* compose_insert_file */
int compose_insert_file(Compose * compose, char const * filename)
{
	int ret = 0;
	FILE * fp;
	GtkTextBuffer * tbuf;
	char buf[BUFSIZ];
	size_t len;
	char * p;
	size_t rlen;
	size_t wlen;
	GError * error = NULL;

	if(filename == NULL)
		return compose_insert_file_dialog(compose);
	/* FIXME use a GIOChannel instead (with a GtkDialog or GtkStatusBar) */
	if((fp = fopen(filename, "r")) == NULL)
	{
		snprintf(buf, sizeof(buf), "%s: %s", filename, strerror(errno));
		return -compose_error(compose, buf, 1);
	}
	tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(compose->view));
	while((len = fread(buf, sizeof(char), sizeof(buf), fp)) > 0)
	{
#if 0
		if((p = g_convert(buf, len, "UTF-8", "ISO-8859-15", &rlen,
						&wlen, NULL)) != NULL)
		{
			gtk_text_buffer_insert_at_cursor(tbuf, p, wlen);
			g_free(p);
		}
		else
			gtk_text_buffer_insert(tbuf, &iter, buf, len);
#else
		if((p = g_locale_to_utf8(buf, len, &rlen, &wlen, &error))
				!= NULL)
			/* FIXME may lose characters */
			gtk_text_buffer_insert_at_cursor(tbuf, p, wlen);
		else
		{
			compose_error(compose, error->message, 1);
			g_error_free(error);
			error = NULL;
			gtk_text_buffer_insert_at_cursor(tbuf, buf, len);
		}
#endif
	}
	if(ferror(fp))
	{
		snprintf(buf, sizeof(buf), "%s: %s", filename, strerror(errno));
		ret = -compose_error(compose, buf, 1);
	}
	fclose(fp);
	compose_set_modified(compose, TRUE);
	return ret;
}
Ejemplo n.º 3
0
void compose_send(Compose * compose)
{
	/* FIXME rewrite more efficiently (and tracking process) */
	char * msg;
	size_t msg_len;
	char * body;
	size_t body_len;
	char * p;

	if((msg = _send_headers(compose)) == NULL)
		return;
	if((body = _send_body(compose->view)) == NULL)
	{
		free(msg);
		return;
	}
	msg_len = strlen(msg);
	body_len = strlen(body);
	if((p = realloc(msg, msg_len + body_len + 8)) == NULL)
		compose_error(compose, strerror(errno), 0);
	else
	{
		msg = p;
		snprintf(&msg[msg_len], body_len + 8, "\r\n%s\r\n.\r\n", body);
		msg_len += body_len + 7;
		_send_mail(compose, msg, msg_len);
	}
	g_free(body);
}
Ejemplo n.º 4
0
static gboolean _on_send_write(GIOChannel * source, GIOCondition condition,
		gpointer data)
{
	Compose * compose = data;
	gsize i;

	if(condition != G_IO_OUT)
		return FALSE;
	if((i = (compose->buf_len - compose->buf_pos) % 512) == 0)
		i = 512;
	if(g_io_channel_write_chars(source, &compose->buf[compose->buf_pos], i,
				&i, NULL) != G_IO_STATUS_NORMAL)
	{
		compose_error(compose, strerror(errno), FALSE);
		compose_send_cancel(compose);
		return FALSE;
	}
	compose->buf_pos += i;
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(compose->snd_progress),
			compose->buf_pos / compose->buf_len);
	if(compose->buf_pos >= compose->buf_len)
	{
		compose_send_cancel(compose);
		_compose_delete(compose);
		return FALSE;
	}
	return TRUE;
}
Ejemplo n.º 5
0
static int _send_mail(Compose * compose, char * msg, size_t msg_len)
{
	int fd[2];
	GtkWidget * hbox;
	GtkWidget * widget;

	if(pipe(fd) != 0 || (compose->pid = fork()) == -1)
		return compose_error(compose, strerror(errno), 1);
	if(compose->pid == 0)
		return _mail_child(compose, fd);
	if(close(fd[0]) != 0 || fcntl(fd[1], F_SETFL, O_NONBLOCK) == -1)
		compose_error(compose, strerror(errno), 0);
	compose->snd_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(compose->snd_window),
			_("Sending mail..."));
	gtk_window_set_resizable(GTK_WINDOW(compose->snd_window), FALSE);
	gtk_window_set_transient_for(GTK_WINDOW(compose->snd_window),
			GTK_WINDOW(compose->window));
	g_signal_connect_swapped(G_OBJECT(compose->snd_window), "delete-event",
			G_CALLBACK(_on_send_closex), compose);
#if GTK_CHECK_VERSION(3, 0, 0)
	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
#else
	hbox = gtk_hbox_new(FALSE, 0);
#endif
	gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(_("Progress: ")),
			FALSE, FALSE, 0);
	compose->snd_progress = gtk_progress_bar_new();
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(compose->snd_progress),
			0.0);
	gtk_box_pack_start(GTK_BOX(hbox), compose->snd_progress, TRUE, TRUE, 0);
	widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
	g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(
				compose_send_cancel), compose);
	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
	gtk_container_set_border_width(GTK_CONTAINER(compose->snd_window), 4);
	gtk_container_add(GTK_CONTAINER(compose->snd_window), hbox);
	gtk_widget_show_all(compose->snd_window);
	compose->fd = fd[1];
	compose->buf = msg;
	compose->buf_len = msg_len;
	compose->buf_pos = 0;
	compose->channel = g_io_channel_unix_new(fd[1]);
	g_io_add_watch(compose->channel, G_IO_OUT, _on_send_write, compose);
	return 0;
}
Ejemplo n.º 6
0
static char * _send_headers(Compose * compose)
{
	/* FIXME rewrite this function */
	char * msg = NULL;
	size_t msg_len = 0;
	char * p;
	GtkTreeModel * model = GTK_TREE_MODEL(compose->h_store);
	GtkTreeIter iter;
	gboolean valid;
	char * field;
	size_t field_len;
	char * value;
	char const * q;

#if GTK_CHECK_VERSION(2, 24, 0)
	p = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(
				compose->from));
#else
	p = gtk_combo_box_get_active_text(GTK_COMBO_BOX(compose->from));
#endif
	if(*p != '\0')
	{
		msg_len = strlen(p) + 8;
		if((msg = malloc(msg_len + 1)) == NULL)
			return NULL;
		snprintf(msg, msg_len + 1, "%s%s\r\n", "From: ", p);
	}
	g_free(p);
	valid = gtk_tree_model_get_iter_first(model, &iter);
	for(; valid == TRUE; valid = gtk_tree_model_iter_next(model, &iter))
	{
		gtk_tree_model_get(model, &iter, 0, &field, 1, &value, -1);
		if(field == NULL || value == NULL
				|| (field_len = strlen(field)) == 0
				|| field[field_len - 1] != ':'
				|| index(field, ':') != field + field_len - 1)
		{
			g_free(field);
			g_free(value);
			continue; /* XXX report error */
		}
		if((p = realloc(msg, msg_len + strlen(field) + strlen(value)
						+ 4)) == NULL)
		{
			g_free(field);
			g_free(value);
			continue; /* XXX report error */
		}
		msg = p;
		strcat(msg, field);
		strcat(msg, " ");
		strcat(msg, value);
		strcat(msg, "\r\n");
		msg_len = strlen(msg); /* XXX ugly */
		g_free(field);
		g_free(value);
	}
	q = gtk_entry_get_text(GTK_ENTRY(compose->subject));
	msg_len += strlen(q) + 11;
	if((p = realloc(msg, msg_len + 1)) == NULL)
		return NULL;
	msg = p;
	strcat(msg, "Subject: ");
	strcat(msg, q);
	strcat(msg, "\r\n");
	if(msg != NULL)
		return msg;
	if((msg = strdup("")) == NULL)
		compose_error(compose, strerror(errno), 0);
	return msg;
}
Ejemplo n.º 7
0
Compose * compose_new(Config * config)
{
	Compose * compose;
	GtkAccelGroup * group;
	GtkWidget * vbox;
	GtkWidget * toolbar;
	GtkToolItem * toolitem;
	GtkSizeGroup * sizegroup;
	GtkWidget * vpaned;
	GtkWidget * vbox2;
	GtkWidget * widget;
	GtkCellRenderer * renderer;
	GtkTreeViewColumn * column;
	GtkTreeIter iter;
	char const * headers[] = {
		"To:", "Cc:", "Bcc:", "Reply-To:", "Newsgroup:",
		"Followup-To:" };
	size_t i;

	if((compose = malloc(sizeof(*compose))) == NULL)
	{
		compose_error(NULL, strerror(errno), 0);
		return NULL;
	}
	compose->mime = mime_new(NULL);
	/* check errors */
	if(compose->mime == NULL)
	{
		free(compose);
		return NULL;
	}
	compose->config = config;
	compose->standalone = FALSE;
	/* window */
	group = gtk_accel_group_new();
	compose->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_add_accel_group(GTK_WINDOW(compose->window), group);
#ifndef EMBEDDED
	gtk_window_set_default_size(GTK_WINDOW(compose->window), 512, 384);
#else
	gtk_window_set_default_size(GTK_WINDOW(compose->window), 200, 300);
#endif
	gtk_window_set_title(GTK_WINDOW(compose->window), _("Compose"));
#if GTK_CHECK_VERSION(2, 6, 0)
	gtk_window_set_icon_name(GTK_WINDOW(compose->window), "mailer");
#endif
	g_signal_connect_swapped(G_OBJECT(compose->window), "delete-event",
			G_CALLBACK(_compose_on_closex), compose);
	vbox = gtk_vbox_new(FALSE, 0);
	/* menubar */
#ifndef EMBEDDED
	widget = desktop_menubar_create(_compose_menubar, compose, group);
	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
#endif
	/* toolbar */
	toolbar = desktop_toolbar_create(_compose_toolbar, compose, group);
	gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, TRUE, 0);
	/* from */
	sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
	toolbar = gtk_toolbar_new();
	widget = gtk_label_new(_("From: "));
	gtk_misc_set_alignment(GTK_MISC(widget), 0.1, 0.5);
	gtk_widget_set_size_request(widget, 80, -1);
	gtk_size_group_add_widget(sizegroup, widget);
	toolitem = gtk_tool_item_new();
	gtk_container_add(GTK_CONTAINER(toolitem), widget);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
#if GTK_CHECK_VERSION(2, 24, 0)
	compose->from = gtk_combo_box_text_new_with_entry();
#else
	compose->from = gtk_combo_box_entry_new_text();
#endif
	toolitem = gtk_tool_item_new();
	gtk_tool_item_set_expand(toolitem, TRUE);
	gtk_container_add(GTK_CONTAINER(toolitem), compose->from);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
	gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
	/* paned */
	vpaned = gtk_vpaned_new();
	/* headers */
	widget = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	compose->h_store = gtk_list_store_new(CHC_COUNT, G_TYPE_STRING,
			G_TYPE_STRING, G_TYPE_BOOLEAN);
	compose->h_store_filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(
				compose->h_store), NULL);
	gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(
				compose->h_store_filter),
			_compose_on_headers_filter, compose, NULL);
	compose->h_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(
				compose->h_store_filter));
	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(compose->h_view),
			FALSE);
	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(compose->h_view), TRUE);
	compose->h_headers = gtk_list_store_new(2, G_TYPE_STRING,
			G_TYPE_STRING);
	for(i = 0; i < sizeof(headers) / sizeof(*headers); i++)
	{
		gtk_list_store_append(compose->h_headers, &iter);
		gtk_list_store_set(compose->h_headers, &iter, 0, headers[i], 1,
				headers[i], -1);
	}
	renderer = gtk_cell_renderer_combo_new();
	g_object_set(renderer, "editable", TRUE, "model", compose->h_headers,
			"text-column", 1, NULL);
	g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(
				_on_header_field_edited), compose);
	column = gtk_tree_view_column_new_with_attributes("", renderer, "text",
			CHC_HEADER, NULL);
	gtk_tree_view_column_set_min_width(column, 80);
	gtk_tree_view_append_column(GTK_TREE_VIEW(compose->h_view), column);
	renderer = gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
	g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(
				_on_header_edited), compose);
	column = gtk_tree_view_column_new_with_attributes("", renderer, "text",
			CHC_VALUE, NULL);
#if GTK_CHECK_VERSION(2, 4, 0)
	gtk_tree_view_column_set_expand(column, TRUE);
#endif
	gtk_tree_view_append_column(GTK_TREE_VIEW(compose->h_view), column);
	/* default to 8-bits transfers with UTF-8 encoding */
	compose_set_header(compose, "Content-Transfer-Encoding:", "8bit",
			FALSE);
	compose_set_header(compose, "Content-Type:",
			"text/plain; charset=UTF-8", FALSE);
	compose_add_field(compose, "To:", NULL);
	gtk_container_add(GTK_CONTAINER(widget), compose->h_view);
	gtk_paned_add1(GTK_PANED(vpaned), widget);
	/* paned */
	vbox2 = gtk_vbox_new(FALSE, 0);
	/* subject */
	toolbar = gtk_toolbar_new();
	widget = gtk_label_new(_("Subject: "));
	gtk_misc_set_alignment(GTK_MISC(widget), 0.1, 0.5);
	gtk_size_group_add_widget(sizegroup, widget);
	toolitem = gtk_tool_item_new();
	gtk_container_add(GTK_CONTAINER(toolitem), widget);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
	compose->subject = gtk_entry_new();
	toolitem = gtk_tool_item_new();
	gtk_tool_item_set_expand(toolitem, TRUE);
	gtk_container_add(GTK_CONTAINER(toolitem), compose->subject);
	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
	gtk_box_pack_start(GTK_BOX(vbox2), toolbar, FALSE, TRUE, 0);
	/* view */
	widget = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	compose->view = _new_text_view(compose);
	compose_set_font(compose, _compose_get_font(compose));
	gtk_container_add(GTK_CONTAINER(widget), compose->view);
	gtk_box_pack_start(GTK_BOX(vbox2), widget, TRUE, TRUE, 0);
	gtk_paned_add2(GTK_PANED(vpaned), vbox2);
	gtk_box_pack_start(GTK_BOX(vbox), vpaned, TRUE, TRUE, 0);
	/* attachments */
	compose->a_window = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(compose->a_window),
			GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
	compose->a_store = gtk_list_store_new(CAC_COUNT, G_TYPE_STRING,
			G_TYPE_STRING, GDK_TYPE_PIXBUF);
	compose->a_view = gtk_icon_view_new_with_model(GTK_TREE_MODEL(
				compose->a_store));
	gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(compose->a_view),
			CAC_ICON);
	gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(compose->a_view),
			GTK_SELECTION_MULTIPLE);
	gtk_icon_view_set_text_column(GTK_ICON_VIEW(compose->a_view),
			CAC_BASENAME);
	gtk_container_add(GTK_CONTAINER(compose->a_window), compose->a_view);
	gtk_widget_show_all(compose->a_view);
	gtk_widget_set_no_show_all(compose->a_window, TRUE);
	gtk_box_pack_start(GTK_BOX(vbox), compose->a_window, FALSE, TRUE, 0);
	/* statusbar */
	compose->statusbar = gtk_statusbar_new();
	compose->statusbar_id = 0;
	gtk_box_pack_start(GTK_BOX(vbox), compose->statusbar, FALSE, TRUE, 0);
	gtk_container_add(GTK_CONTAINER(compose->window), vbox);
	/* about dialog */
	compose->ab_window = NULL;
	/* signature */
	compose_append_signature(compose);
	compose_set_modified(compose, FALSE);
	compose_scroll_to_offset(compose, 0);
	/* display */
	gtk_widget_grab_focus(compose->view);
	gtk_widget_show_all(vbox);
	gtk_widget_show(compose->window);
	return compose;
}