# File: msgeditbox.py
# Purpose: window with all associated crap for editing messages

import utils
import gtk
import pango
import os.path
import string
from addressbook import *
from pyneheaders import *
import time
import pynei18n
import boxtypes
import ptk.progresswin
import ptk.misc_widgets
import threading
import tempfile
import gobject
from utils import _u

class msgeditbox(gtk.Window):
	"""
	Window with all associated crap for editing messages
	"""
	def external_editor(self):
		filename = tempfile.mktemp(".txt")

		f = open(filename, "w")
		f.write(self.msg.body)
		f.close()

		os.system("%s %s" % (self.user.edit_cmd, filename))

		f = open(filename, "r")
		self.msg.body = f.read()
		f.close()

		os.remove(filename)
		
		# Some things are required XXX XXX XXX
		# subject, to
		#if not self.msg.headers.has_key("subject"):
		#	self.msg.headers["subject"] = ""
		#if _("Newsgroups") in self.view_fields:
		#	if not self.msg.headers.has_key("newsgroups"):
		#		self.msg.headers["newsgroups"] = ""
		#else:
		#	if not self.msg.headers.has_key("to"):
		#		self.msg.headers["to"] = ""
	
		self.msg.parseheaders(self.user)
		# Create new body text
		self.msg.make_source()
		self.msg.opts = self.msg.opts | MSG_ISREAD
		self.folder.save_article(self.msg)

		# Update message list
		self.folder.changed = 1

		self.user.queue_action(ACT_UPDATE)

	def __init__(self, msg, folder, user, is_new_msg=0):
		"""
		Folder will most likely be the outbox.
		"""
		from pyne import pyne_path
		# Store some shit
		self.msg = msg
		self.folder = folder
		self.send_folder = user.get_folder_by_uid(msg.senduid)
		self.user = user
		self.any_changes = 0

		# Use external editor
		if user.opts & OPT_EXT_EDITOR:
			# Spawn a thread so we can wait on external editor
			threading.Thread(target=self.external_editor).start()
			return

		if msg.headers.has_key("newsgroups"):
			self.view_fields = [ _("From"), _("Reply-To"), _("Newsgroups"), _("Subject"), _("Organization") ]
			self.fields = [ 0, 2, 3 ] # from, to, newsgroups
		else:
			self.view_fields = [ _("From"), _("Reply-To"), _("To"), _("Cc"), _("Bcc"), _("Subject"), _("Organization") ]
			self.fields = [ 0, 2, 5 ] # from, to, subject

		gtk.Window.__init__(self)
		self.set_default_size(600,440)
		self.set_title(_("Pyne - Message Composer"))

		box1 = gtk.VBox()
		self.add(box1)
		box1.show()

		# only pygtk-2.2
		if gtk.__dict__.has_key ("Clipboard"):
			self.clipboard = gtk.Clipboard (gtk.gdk.display_get_default(),"CLIPBOARD")
		else:
			self.clipboard = None

		# UIManager is cool!
		self.ui = gtk.UIManager ()
		self.ui.add_ui_from_file (os.path.join (pyne_path, "ui_msgeditbox.xml"))

		self.actgroups = {}

		def _actgroup_new (name, actions):
			self.actgroups[name] = gtk.ActionGroup (name)
			self.actgroups[name].add_actions (actions)
			self.ui.insert_action_group (self.actgroups[name], 0)
			
		_actgroup_new ("AlwaysOn", [
			("MessageMenu", None, _("_Message"), None, None),
			("Delete", "gtk-delete", _("_Delete"), None, None, self.nuke_msg),
			("SaveTo", None, _("Save _to"), None, None),
			("SaveChanges", None, _("_Save changes"), "<Control>S", None, self.save_changes),
			("QueueMsg", None, _("Queue"), "<Control>D", None, self.queue_msg),
			("SendNow", None, _("Send _Now"), None, None, self.send_now),
			("SaveAndClose", None, _("Save and _Close"), None, None, self.finish_edit),

			("EditMenu", None, _("_Edit"), None, None),
			("Cut", None, _("_Cut"), "<Control>X", None, self.edit_cut),
			("Copy", None, _("C_opy"), "<Control>C", None, self.edit_copy),
			("Paste", None, _("_Paste"), "<Control>V", None, self.edit_paste),
			("ROT13", None, _("ROT13"), None, None, self.rot13_sel),
			("InsertFile", None, _("_Insert File"), None, None, self.insert_file),
		])

		self.menubar = self.ui.get_widget ("/MenuBar")
		self.add_accel_group (self.ui.get_accel_group ())
		box1.pack_start(self.menubar, expand=False)
		
		
		# Build save-to menu
		menuitem = self.ui.get_widget ("/MenuBar/Message/SaveTo")
		menu = gtk.Menu()
		menuitem.set_submenu (menu)
		def _get_good_saveboxes (folder):
			if folder.uid in ("deleted", "sent"): return
			if isinstance (folder, boxtypes.storebox.storebox) or \
			   isinstance (folder, boxtypes.outbox.outbox):
				return folder
		f_list = utils.recurse_apply (user.contents, _get_good_saveboxes)
		group = None
		for i in f_list:
			menuitem = gtk.RadioMenuItem(group, i.name)
			group = menuitem
			menuitem.connect("toggled", self.save_to_folder, i.uid)
			menu.append(menuitem)
			menuitem.show()
			if i.uid == self.folder.uid:
				menuitem.set_active (True)
		menu.show()
		
		# make headers submenu
		viewmenu = gtk.MenuItem(_("View"))
		menu = gtk.Menu()
		for i in range(0, len(self.view_fields)):
			menuitem = gtk.CheckMenuItem(self.view_fields[i])
			# set state
			if i in self.fields:
				menuitem.set_active(True)
			else:
				menuitem.set_active(False)
			menuitem.connect("toggled", self.toggle_view, i)
			#menuitem.set_data("user_data", i)
			menu.append(menuitem)
			menuitem.show()
		menu.show()
		viewmenu.set_submenu(menu)
		self.menubar.append(viewmenu)
		viewmenu.show()

		# nessage options menu
		optsmenu = gtk.MenuItem(_("Options"))
		menu = gtk.Menu()
		
		menuitem = gtk.CheckMenuItem(_("Confirm Delivery"))
		if msg.headers.has_key("return-receipt-to"):
			menuitem.set_active(True)
		else:
			menuitem.set_active(False)
		menuitem.connect("toggled", self.toggle_getreceipt)
		menu.append(menuitem)
		menuitem.show()
		menu.show()
		optsmenu.set_submenu(menu)
		self.menubar.append(optsmenu)
		optsmenu.show()

		# make 'send from' menu
		sendfrommenu = gtk.MenuItem(_("Send With..."))
		menu = gtk.Menu()
		# If it has been deleted we have to be smart...
		if self.send_folder == None:
			# News posting or email?
			if msg.headers.has_key("newsgroups"):
				good_class = boxtypes.nntpbox.nntpbox
			else:
				good_class = boxtypes.mailbox.mailbox
		else:
			good_class = self.send_folder.__class__
		# make list of suitable folders
		def _get_good_sendboxes(folder, good_class=good_class):
			# enforce same folder type
			if isinstance(folder, good_class):
				if folder.__dict__.has_key("send_type"):
					# disallow mailboxes with no send server
					if folder.send_type == 0:
						return
				return folder
		f_list = utils.recurse_apply(user.contents, _get_good_sendboxes)
		# Folder was deleted. change to using first folder found
		if self.send_folder == None and len(f_list) != 0:
			self.send_folder = f_list[0]
		# make a menu of them
		group = None
		for i in f_list:
			menuitem = gtk.RadioMenuItem(group, i.name)
			menuitem.connect("toggled", self.change_send_folder, i.uid)
			group = menuitem
			menu.append(menuitem)
			menuitem.show()
			if i is self.send_folder:
				menuitem.set_active(True)
		menu.show()
		sendfrommenu.set_submenu(menu)
		self.menubar.append(sendfrommenu)
		sendfrommenu.show()

		# personalities menu
		personmenu = gtk.MenuItem(_("Personalities"))
		menu = gtk.Menu()
		group = None
		for i in self.send_folder.personalities:
			menuitem = gtk.RadioMenuItem(group, user.get_personality(i).pname)
			menuitem.connect("toggled", self.change_personality, i)
			group = menuitem
			menu.append(menuitem)
			menuitem.show()
			if self.send_folder.default_personality == i:
				menuitem.set_active(True)
		menu.show()
		personmenu.set_submenu(menu)
		self.menubar.append(personmenu)
		personmenu.show()

		self.menubar.show ()

		#############

		entry_box = gtk.VBox()
		entry_box.set_border_width(5)
		box1.pack_start(entry_box, expand=False)
		entry_box.show()
		
		entry_table = gtk.Table(3, len(self.view_fields), False)
		entry_table.set_row_spacings(5)
		entry_table.set_col_spacings(5)
		entry_box.pack_start(entry_table, expand=True)
		entry_table.show()
	
		def get_to_address(_button, self=self):
			gtkentry = self.header_boxes[_("To")][1]
			addr_box = AddressEditBox(self.user.addressbook, self, gtkentry, append=1)

		def get_reply_to_address(_button, self=self):
			gtkentry = self.header_boxes[_("Reply-To")][1]
			addr_box = AddressEditBox(self.user.addressbook, self, gtkentry)

		def get_from_address(_button, self=self):
			gtkentry = self.header_boxes[_("From")][1]
			addr_box = AddressEditBox(self.user.addressbook, self, gtkentry)

		def get_cc_address(_button, self=self):
			gtkentry = self.header_boxes[_("Cc")][1]
			addr_box = AddressEditBox(self.user.addressbook, self, gtkentry, append=1)

		def get_bcc_address(_button, self=self):
			gtkentry = self.header_boxes[_("Bcc")][1]
			addr_box = AddressEditBox(self.user.addressbook, self, gtkentry, append=1)

		# stored in form { "header name": (gtkbox, gtklabel, gtkentry, gtkbutton) }
		self.header_boxes = {}
		for x in range(0, len(self.view_fields)):
			header = self.view_fields[x]

			label = gtk.Label(header+": ")
			entry_table.attach(label, 0,1, x,x+1, xoptions=gtk.SHRINK)

			entry = gtk.Entry()
			if msg.headers.has_key(string.lower(header)):
				entry.set_text(msg.headers[string.lower(header)])

			# some headers access to the address book is appropriate
			if header==_("To") or header==_("From") or header==_("Reply-To") \
					or header==_("Cc") or header==_("Bcc"):
				button = gtk.Button(" ... ")
				button.gtkentry = entry
				if header==_("To"):
					button.connect("clicked", get_to_address)
				if header==_("From"):
					button.connect("clicked", get_from_address)
				if header==_("Cc"):
					button.connect("clicked", get_cc_address)
				if header==_("Bcc"):
					button.connect("clicked", get_bcc_address)
				if header==_("Reply-To"):
					button.connect("clicked", get_reply_to_address)
				entry_table.attach(entry, 1,2, x,x+1, xoptions=gtk.EXPAND|gtk.FILL)
				entry_table.attach(button, 2,3, x,x+1, xoptions=gtk.SHRINK)
				self.header_boxes[header] = (label, entry, button)
			else:
				entry_table.attach(entry, 1,3, x,x+1, xoptions=gtk.EXPAND|gtk.FILL)
				self.header_boxes[header] = (label, entry, None)

		self.update_view_headers()

		# 'Notebook' for body and attachments.
		notebook = gtk.Notebook()
		notebook.set_tab_pos(user.tab_pos)
		box1.pack_start(notebook)
		notebook.show()

#		def _do_wrap(_a, self=self, font=font, col_text=col_text):
#			self.any_changes = 1
#			# get text before the cursor
#			text = self.msg_text.get_chars(0, self.msg_text.get_length())
#			pos = self.msg_text.get_point()
#
#			# find line with cursor on
#			text_to = text[:pos]
#			line = string.split(text_to, "\n")[-1]
#
#			# insert newline if we exceed line length, and
#			# have finished a word
#			if len(line) > self.user.linewrap and text[pos-1] == " ":
#				# delete space, then insert newline
#				self.msg_text.delete_text(pos-1, pos)
#				self.msg_text.insert(font, col_text, None, "\n")

		# text editty bit
		label = gtk.Label(_("Body"))

		swin = gtk.ScrolledWindow()
		swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		swin.set_shadow_type(gtk.SHADOW_IN)
		notebook.append_page(swin, label)
		swin.show()

		self.msg_textview = gtk.TextView()
		self.msg_textview.set_editable(True)
		self.msg_textview.modify_font ( pango.FontDescription (user.bodyfont) )
		self.msg_textview.set_wrap_mode (gtk.WRAP_WORD)
		#self.msg_textview.connect("changed", _do_wrap)
		swin.add(self.msg_textview)
		self.msg_textview.show()
		
		textbuffer = self.msg_textview.get_buffer()
		
		# Text tags and such poo
		tag_table = textbuffer.get_tag_table()

		self.body_tag = gtk.TextTag("body")
		self.body_tag.set_property("foreground", user.col_text)
		tag_table.add(self.body_tag)

		self.quote_tag = gtk.TextTag("quote")
		self.quote_tag.set_property("foreground", user.col_quote)
		tag_table.add(self.quote_tag)
		
		# Dump it
		msg_lines = string.split(msg.parts_text[0], "\n")
		if msg_lines[len(msg_lines)-1] == "":
			del msg_lines[len(msg_lines)-1]
		for x in range (0, len(msg_lines)):
			# Quoted ([:1] == [0] w/o raising exception on "")
			if msg_lines[x][:1] == '>':
				# A bit ugly.. make sure text inserted around
				# this ends up 'col_text' not 'col_quote'
				pos = textbuffer.get_char_count()
				textbuffer.insert_with_tags(textbuffer.get_end_iter(), ">", self.body_tag)
				textbuffer.insert_with_tags(textbuffer.get_end_iter(), msg_lines[x][1:]+"\n", self.quote_tag)
				continue
			# Normal
			else:
				pos = textbuffer.get_char_count()
				textbuffer.insert_with_tags(textbuffer.get_end_iter(), msg_lines[x]+"\n", self.body_tag)
				continue
		# delete trailing \n we added
		end_minus_one = textbuffer.get_end_iter()
		end_minus_one.backward_char()
		textbuffer.delete(end_minus_one, textbuffer.get_end_iter())

		# position cursor at start of message
		textbuffer.place_cursor (textbuffer.get_start_iter ())

		# attachments bit
		box2 = gtk.VBox()
		self.attach_label = gtk.Label(_("Attachments"))
		notebook.append_page(box2, self.attach_label)
		box2.show()

		cell = gtk.CellRendererText()
		self.attachment_list = gtk.TreeView()
		
		col = gtk.TreeViewColumn(_("Type"), cell, text=0)
		col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
		self.attachment_list.append_column(col)
		col = gtk.TreeViewColumn(_("Name"), cell, text=1)
		col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
		self.attachment_list.append_column(col)
		col = gtk.TreeViewColumn(_("Size"), cell, text=2)
		col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
		self.attachment_list.append_column(col)
		
		self.selected_attachment = None
	
		swin = gtk.ScrolledWindow()
		swin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		swin.set_shadow_type(gtk.SHADOW_IN)
		box2.pack_start(swin)
		swin.show()
		swin.add(self.attachment_list)
		self.attachment_list.show()
	
		# Stick attachments into it
		self.update_attachment_list()
			
		def _on_click(widget, event, self=self):
			x, y = event.x, event.y
			# Path of clicked on item
			selected = widget.get_path_at_pos(x,y)
			if selected == None:
				return
			# Get tree iter from path
			iter = self.model.get_iter(selected[0])
			# Invisible field gives attachment index
			self.selected_attachment = self.model.get_value(iter, 3)

		# View attachment on click
		self.attachment_list.connect("button_press_event", _on_click)
		
		box3 = gtk.HBox(spacing=5)
		box3.set_border_width(5)
		box2.pack_start(box3, expand=False)
		box3.show()

		button = gtk.Button(" "+_("Delete")+" ")
		button.connect("clicked", self.del_attach)
		box3.pack_end(button, expand=False)
		button.show()

		button = gtk.Button(" "+_("Add")+" ")
		button.connect("clicked", self.add_attach)
		box3.pack_end(button, expand=False)
		button.show()

		self.show()

		if is_new_msg == 1:
			self.connect("delete_event", self.ask_if_save)
		else:
			self.connect("delete_event", self.finish_edit)
	
	def ask_if_save (self, _gtkobj, _poop):
		ret = ptk.misc_widgets.ReturnDialog (_("Save message?"), _("Your new message is unsaved.\nWhat would you like to do?"), ((gtk.STOCK_SAVE,1), (gtk.STOCK_DELETE,0)), parent_win=self)
		if ret == 0:
			self.nuke_msg ()
		else:
			self.finish_edit ()
	
	def toggle_view(self, _gtkobj, index):
		# Toggle show header
		if index in self.fields:
			self.fields.remove(index)
		else:
			self.fields.append(index)
		self.update_view_headers()
	
	def toggle_getreceipt(self, _gtkobj):
		# Add "Return-Receipt-To header
		if self.msg.headers.has_key("return-receipt-to"):
			del self.msg.headers["return-receipt-to"]
		else:
			self.msg.headers["return-receipt-to"] = self.msg.headers["from"]
	
	def change_personality(self, _gtkobj, uid):
		#
		persn = self.user.get_personality(uid)

		# Gtk fires one before we are ready :-)
		if not self.__dict__.has_key("header_boxes"):
			return
		
		self.header_boxes[_("From")][1].set_text("\""+persn.realname+"\" <"+persn.emailaddr+">")
		self.header_boxes[_("Reply-To")][1].set_text(persn.replyto)
		self.header_boxes[_("Organization")][1].set_text(persn.org)
	
	def change_send_folder(self, _gtkobj, uid):
		# change which folder we are sending with
		self.msg.senduid = uid
			
	def save_to_folder (self, gtkobj, uid):
		# the send-to radio menu thing causes a spurious save_to_folder, before
		# self.msg_textview exists.
		if not self.__dict__.has_key ("msg_textview"): return
		self.save_changes ()
		if self.folder.uid != uid:
			self.folder.move_article (self.user, self.msg.headers["message-id"], uid)
			self.folder = self.user.get_folder_by_uid (uid)
			self.user.update ()

	def update_view_headers(self):
		# .show() objects as required
		for x in self.header_boxes.keys():
			label, entry, button = self.header_boxes[x]
			try:
				index = self.view_fields.index(x)
			except ValueError:
				print "weird"
				continue
			else:
				if index in self.fields:
					label.show()
					entry.show()
					if button != None:
						button.show()
				else:
					# not present. this header should be hidden
					label.hide()
					entry.hide()
					if button != None:
						button.hide()
		# contract if we hid some :-)
		self.queue_resize()

	def open_address_book(self, _button):
		AddressEditBox(self.user.addressbook, self, _button.gtkentry)

	def rot13_sel(self, _a=0, _b=0, _c=0):
		"""
		ROT13 'encode' the selected text.
		"""
		textbuffer = self.msg_textview.get_buffer()

		# Selection positions
		insert_iter = textbuffer.get_iter_at_mark(textbuffer.get_mark("insert"))
		bound_iter = textbuffer.get_iter_at_mark(textbuffer.get_mark("selection_bound"))

		text = textbuffer.get_slice(insert_iter, bound_iter, 0)
		text = text.encode('rot13')
		textbuffer.delete(insert_iter, bound_iter)
		# dump into widget
		textbuffer.insert(insert_iter, text)
		
	def edit_cut(self, _a=0, _button=0, _b=0):
		self.msg_textview.get_buffer().cut_clipboard(self.clipboard, True)

	def edit_copy(self, _a=0, _button=0, _b=0):
		self.msg_textview.get_buffer().copy_clipboard(self.clipboard)

	def edit_paste(self, _a=0, _button=0, _b=0):
		def _clipboard_callback (clipboard, text, data):
			print text
			self.msg_textview.get_buffer ().insert_at_cursor (text, len(text))
		#if self.clipboard:
		#	self.clipboard.request_text (_clipboard_callback)
		# paste_clipboard doesn't work with TextIter = None... so we
		# use the above hack.
		# But it won't work either since it needs pygtk 2.4 and is untested code...
		self.msg_textview.get_buffer().paste_clipboard(self.clipboard, None, True)

	def insert_file(self, _a=0, _button=0, _b=0):
		def do_it(filename, self=self):
			if filename == None:
				return
			try:
				file = open(filename, "r")
				text = file.read().replace("\0", "")
			except IOError:
				ptk.misc_widgets.InfoBox (_("Error"), _("Could not open %s") % filename, gtk.STOCK_OK, parent_win=self)
				return
			# dump into widget
			textbuffer = self.msg_textview.get_buffer()
			textbuffer.insert_at_cursor(_u(text), len(_u(text)))
		
		# Open file selection box
		fsel = ptk.misc_widgets.FileSelectorBox(self.user, _("Insert text file inline"), "", do_it)
		fsel.set_transient_for(self)
		fsel.show()
	
	def update_attachment_list(self):
		"""
		Update the attachment list.
		"""
		list_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT)
		self.selected_attachment = None

		for x in range(1, len(self.msg.parts_text)):
			a = self.msg.get_attachment_info(x)

			iter = list_store.append()
			list_store.set(iter, 0, a[0], 1, a[1], 2, a[2], 3, x)

		self.attach_label.set_text(_("Attachments")+" ("+str(len(self.msg.parts_text)-1)+")")
		self.attachment_list.set_model(list_store)
		self.model = list_store

	def add_attach(self, _button):
		"""
		Get filename to save attachment.
		"""
		def do_it(filename, self=self):
			if filename == None:
				return
			if os.path.isfile(filename) == 0:
				return
			self.msg.add_attachment(filename)
			self.update_attachment_list()
		# Open file selection box
		fsel = ptk.misc_widgets.FileSelectorBox(self.user, _("Add attachment"), "", do_it)
		fsel.set_transient_for(self)
		fsel.show()

	def del_attach(self, _button):
		"""
		View attachment.
		"""
		# No attachments
		selected = self.selected_attachment
		if selected == None:
			return
		# Delete attachment
		del self.msg.parts_text[selected]
		del self.msg.parts_header[selected]

		self.update_attachment_list()

	def nuke_msg(self, _a=0, _b=0, save_if_changed=0):
		"""
		Remove the message we are editing.
		XXX currently self.any_changes isn't set. it was in gtk-1.x code.
		"""
		if self.any_changes==1 and save_if_changed==1:
			self.finish_edit()
			return
		self.folder.delete_article(self.msg.headers["message-id"])
		
		# Update message list
		self.folder.changed = 1
		self.user.update()

		self.destroy()

	def send_now(self, _a=0, _b=0, _c=0):
		import threading
		# save changes
		self.save_to_folder (None, "outbox")
		self.destroy ()

		pager = ptk.progresswin.ProgressWin(_("Sending message..."), self.user, hidetext=_("Show Logs"))
		outbox = self.user.get_folder_by_uid("outbox")
		
		threading.Thread(target=outbox.send_one,args=(self.user, pager.get_progress_bar(), self.msg.headers["message-id"])).start()

	def save_changes (self, _a=None, _b=None):
		"""
		Save changes to message.
		"""
		textbuffer = self.msg_textview.get_buffer()
		temp = textbuffer.get_slice(textbuffer.get_start_iter(), textbuffer.get_end_iter(), 0)

		# Weird gtk.Text bugs appear unless a terminating "\n"
		# is present
		if temp[-1:] != "\n":
			temp = temp + "\n"
		if (len(self.msg.parts_text)==0):
			self.msg.parts_text.append(temp)
		else:
			self.msg.parts_text[0] = temp
		self.msg.body = temp

		# Collect edited headers:
		for x in self.view_fields:
			gtkentry = self.header_boxes[x][1]
			s = gtkentry.get_text()
			if s == "":
				if self.msg.headers.has_key(string.lower(x)):
					del self.msg.headers[string.lower(x)]
			else:
				self.msg.headers[string.lower(x)] = s
		
		# Some things are required XXX XXX XXX
		# subject, to
		if not self.msg.headers.has_key("subject"):
			self.msg.headers["subject"] = ""
		if _("Newsgroups") in self.view_fields:
			if not self.msg.headers.has_key("newsgroups"):
				self.msg.headers["newsgroups"] = ""
		else:
			if not self.msg.headers.has_key("to"):
				self.msg.headers["to"] = ""
	
		# 'Touch' the time flag
		self.msg.date = int(time.time())

		# Create new body text
		self.msg.make_source()
		self.msg.opts = self.msg.opts | MSG_ISREAD
		self.folder.save_article(self.msg)

		# Update message list
		self.folder.changed = 1
		self.user.update()

	def queue_msg (self, _a=None, _b=None):
		"""
		Save message to outbox and close edit window.
		"""
		self.save_to_folder (None, "outbox")
		self.destroy ()

	def finish_edit(self, _a=0, _b=0, _c=0):
		"""
		Save changes to message.
		"""
		self.save_changes ()
		self.destroy()



syntax highlighted by Code2HTML, v. 0.9.1