Remove inclusion of sys/socket.h from nntp-thread.c
[claws.git] / src / plugins / python / composewindowtype.c
blobc6edfb2b58fdba95262e6e8673c08bedc681d24d
1 /* Python plugin for Claws Mail
2 * Copyright (C) 2009 Holger Berndt
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 # include "claws-features.h"
21 #endif
23 #include "composewindowtype.h"
24 #include "accounttype.h"
26 #include "clawsmailmodule.h"
27 #include "foldertype.h"
28 #include "messageinfotype.h"
30 #include "mainwindow.h"
31 #include "account.h"
32 #include "summaryview.h"
33 #include "gtk/combobox.h"
35 #include <glib.h>
36 #include <glib/gi18n.h>
38 #include <structmember.h>
40 #include <string.h>
42 typedef struct {
43 PyObject_HEAD
44 PyObject *ui_manager;
45 PyObject *text;
46 PyObject *replyinfo;
47 PyObject *fwdinfo;
48 Compose *compose;
49 } clawsmail_ComposeWindowObject;
51 static void ComposeWindow_dealloc(clawsmail_ComposeWindowObject* self)
53 Py_XDECREF(self->ui_manager);
54 Py_XDECREF(self->text);
55 Py_XDECREF(self->replyinfo);
56 Py_XDECREF(self->fwdinfo);
57 Py_TYPE(self)->tp_free((PyObject*)self);
60 static void flush_gtk_queue(void)
62 while(gtk_events_pending())
63 gtk_main_iteration();
66 static void store_py_object(PyObject **target, PyObject *obj)
68 Py_XDECREF(*target);
69 if(obj)
71 Py_INCREF(obj);
72 *target = obj;
74 else {
75 Py_INCREF(Py_None);
76 *target = Py_None;
80 static void composewindow_set_compose(clawsmail_ComposeWindowObject *self, Compose *compose)
82 self->compose = compose;
84 store_py_object(&(self->ui_manager), get_gobj_from_address(compose->ui_manager));
85 store_py_object(&(self->text), get_gobj_from_address(compose->text));
87 store_py_object(&(self->replyinfo), clawsmail_messageinfo_new(compose->replyinfo));
88 store_py_object(&(self->fwdinfo), clawsmail_messageinfo_new(compose->fwdinfo));
91 static int ComposeWindow_init(clawsmail_ComposeWindowObject *self, PyObject *args, PyObject *kwds)
93 MainWindow *mainwin;
94 PrefsAccount *ac = NULL;
95 FolderItem *item;
96 GList* list;
97 GList* cur;
98 gboolean did_find_compose;
99 Compose *compose = NULL;
100 const char *ss;
101 unsigned char open_window;
102 /* if __open_window is set to 0/False,
103 * composewindow_set_compose must be called before this object is valid */
104 static char *kwlist[] = {"address", "__open_window", NULL};
106 ss = NULL;
107 open_window = 1;
108 PyArg_ParseTupleAndKeywords(args, kwds, "|sb", kwlist, &ss, &open_window);
110 if(open_window) {
111 mainwin = mainwindow_get_mainwindow();
112 item = mainwin->summaryview->folder_item;
113 did_find_compose = FALSE;
115 if(ss) {
116 ac = account_find_from_address(ss, FALSE);
117 if (ac && ac->protocol != A_NNTP) {
118 compose = compose_new_with_folderitem(ac, item, NULL);
119 did_find_compose = TRUE;
122 if(!did_find_compose) {
123 if (item) {
124 ac = account_find_from_item(item);
125 if (ac && ac->protocol != A_NNTP) {
126 compose = compose_new_with_folderitem(ac, item, NULL);
127 did_find_compose = TRUE;
131 /* use current account */
132 if (!did_find_compose && cur_account && (cur_account->protocol != A_NNTP)) {
133 compose = compose_new_with_folderitem(cur_account, item, NULL);
134 did_find_compose = TRUE;
137 if(!did_find_compose) {
138 /* just get the first one */
139 list = account_get_list();
140 for (cur = list ; cur != NULL ; cur = g_list_next(cur)) {
141 ac = (PrefsAccount *) cur->data;
142 if (ac->protocol != A_NNTP) {
143 compose = compose_new_with_folderitem(ac, item, NULL);
144 did_find_compose = TRUE;
150 if(!did_find_compose)
151 return -1;
153 composewindow_set_compose(self, compose);
154 gtk_widget_show_all(compose->window);
155 flush_gtk_queue();
157 return 0;
160 /* this is here because wrapping GTK_EDITABLEs in PyGTK is buggy */
161 static PyObject* get_python_object_from_gtk_entry(GtkWidget *entry)
163 return Py_BuildValue("s", gtk_entry_get_text(GTK_ENTRY(entry)));
166 static PyObject* set_gtk_entry_from_python_object(GtkWidget *entry, PyObject *args)
168 const char *ss;
170 if(!PyArg_ParseTuple(args, "s", &ss))
171 return NULL;
173 gtk_entry_set_text(GTK_ENTRY(entry), ss);
175 Py_INCREF(Py_None);
176 return Py_None;
179 static PyObject* ComposeWindow_get_subject(clawsmail_ComposeWindowObject *self, PyObject *args)
181 return get_python_object_from_gtk_entry(self->compose->subject_entry);
184 static PyObject* ComposeWindow_set_subject(clawsmail_ComposeWindowObject *self, PyObject *args)
186 PyObject *ret;
187 ret = set_gtk_entry_from_python_object(self->compose->subject_entry, args);
188 flush_gtk_queue();
189 return ret;
192 static PyObject* ComposeWindow_get_from(clawsmail_ComposeWindowObject *self, PyObject *args)
194 return get_python_object_from_gtk_entry(self->compose->from_name);
197 static PyObject* ComposeWindow_set_from(clawsmail_ComposeWindowObject *self, PyObject *args)
199 PyObject *ret;
200 ret = set_gtk_entry_from_python_object(self->compose->from_name, args);
201 flush_gtk_queue();
202 return ret;
205 static PyObject* ComposeWindow_add_To(clawsmail_ComposeWindowObject *self, PyObject *args)
207 const char *ss;
209 if(!PyArg_ParseTuple(args, "s", &ss))
210 return NULL;
212 compose_entry_append(self->compose, ss, COMPOSE_TO, PREF_NONE);
214 flush_gtk_queue();
216 Py_INCREF(Py_None);
217 return Py_None;
220 static PyObject* ComposeWindow_add_Cc(clawsmail_ComposeWindowObject *self, PyObject *args)
222 const char *ss;
224 if(!PyArg_ParseTuple(args, "s", &ss))
225 return NULL;
227 compose_entry_append(self->compose, ss, COMPOSE_CC, PREF_NONE);
229 flush_gtk_queue();
231 Py_INCREF(Py_None);
232 return Py_None;
235 static PyObject* ComposeWindow_add_Bcc(clawsmail_ComposeWindowObject *self, PyObject *args)
237 const char *ss;
239 if(!PyArg_ParseTuple(args, "s", &ss))
240 return NULL;
242 compose_entry_append(self->compose, ss, COMPOSE_BCC, PREF_NONE);
244 flush_gtk_queue();
246 Py_INCREF(Py_None);
247 return Py_None;
250 static PyObject* ComposeWindow_attach(clawsmail_ComposeWindowObject *self, PyObject *args)
252 PyObject *olist;
253 Py_ssize_t size, iEl;
254 GList *list = NULL;
256 if(!PyArg_ParseTuple(args, "O!", &PyList_Type, &olist))
257 return NULL;
259 size = PyList_Size(olist);
260 for(iEl = 0; iEl < size; iEl++) {
261 char *ss;
262 PyObject *element = PyList_GET_ITEM(olist, iEl);
264 if(!element)
265 continue;
267 Py_INCREF(element);
268 if(!PyArg_Parse(element, "s", &ss)) {
269 Py_DECREF(element);
270 if(list)
271 g_list_free(list);
272 return NULL;
274 list = g_list_prepend(list, ss);
275 Py_DECREF(element);
278 compose_attach_from_list(self->compose, list, FALSE);
279 g_list_free(list);
281 flush_gtk_queue();
283 Py_INCREF(Py_None);
284 return Py_None;
287 static PyObject* ComposeWindow_get_header_list(clawsmail_ComposeWindowObject *self, PyObject *args)
289 GSList *walk;
290 PyObject *retval;
292 retval = Py_BuildValue("[]");
293 for(walk = self->compose->header_list; walk; walk = walk->next) {
294 ComposeHeaderEntry *headerentry = walk->data;
295 const gchar *header;
296 const gchar *text;
298 header = gtk_editable_get_chars(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(headerentry->combo))), 0, -1);
299 text = gtk_entry_get_text(GTK_ENTRY(headerentry->entry));
301 if(text && strcmp("", text)) {
302 PyObject *ee;
303 int ok;
305 ee = Py_BuildValue("(ss)", header, text);
306 ok = PyList_Append(retval, ee);
307 Py_DECREF(ee);
308 if(ok == -1) {
309 Py_DECREF(retval);
310 return NULL;
314 return retval;
317 static PyObject* ComposeWindow_set_header_list(clawsmail_ComposeWindowObject *self, PyObject *args)
319 gint num;
320 GSList *walk;
321 PyObject *headerlist;
322 Py_ssize_t headerlistsize;
323 Py_ssize_t iEl;
325 if(!PyArg_ParseTuple(args, "O!", &PyList_Type, &headerlist))
326 return NULL;
328 headerlistsize = PyList_Size(headerlist);
329 num = g_slist_length(self->compose->header_list);
331 /* check correctness of argument before deleting old content */
332 for(iEl = 0; iEl < headerlistsize; iEl++) {
333 PyObject *element;
334 PyObject *headerfield;
335 PyObject *headercontent;
337 /* check that we got a list of tuples with two elements */
338 element = PyList_GET_ITEM(headerlist, iEl);
339 if(!element || !PyObject_TypeCheck(element, &PyTuple_Type) || (PyTuple_Size(element) != 2)) {
340 PyErr_SetString(PyExc_LookupError, "Argument to set_header_list() must be a list of tuples with two bytestrings");
341 return NULL;
344 /* check that the two tuple elements are strings */
345 headerfield = PyTuple_GetItem(element, 0);
346 headercontent = PyTuple_GetItem(element, 1);
347 if(!headerfield || !headercontent
348 || !PyObject_TypeCheck(headerfield, &PyBytes_Type) || !PyObject_TypeCheck(headercontent, &PyBytes_Type)) {
349 PyErr_SetString(PyExc_LookupError, "Argument to set_header_list() must be a list of tuples with two bytestrings");
350 return NULL;
354 /* delete old headers */
355 for(walk = self->compose->header_list; walk; walk = walk->next) {
356 ComposeHeaderEntry *headerentry = walk->data;
357 gtk_entry_set_text(GTK_ENTRY(headerentry->entry), "");
360 /* if given header list is bigger than current header list, add dummy values */
361 while(num < headerlistsize) {
362 compose_entry_append(self->compose, "dummy1dummy2dummy3", COMPOSE_TO, PREF_NONE);
363 num++;
366 /* set headers to new values */
367 for(iEl = 0; iEl < headerlistsize; iEl++) {
368 PyObject *element;
369 PyObject *headerfield;
370 PyObject *headercontent;
371 ComposeHeaderEntry *headerentry;
372 GtkEditable *editable;
373 gint pos;
375 element = PyList_GET_ITEM(headerlist, iEl);
376 headerfield = PyTuple_GetItem(element, 0);
377 headercontent = PyTuple_GetItem(element, 1);
379 headerentry = g_slist_nth_data(self->compose->header_list, iEl);
381 /* set header field */
382 editable = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(headerentry->combo)));
383 gtk_editable_delete_text(editable, 0, -1);
384 gtk_editable_insert_text(editable, PyBytes_AsString(headerfield), -1, &pos);
386 /* set header content */
387 gtk_entry_set_text(GTK_ENTRY(headerentry->entry), PyBytes_AsString(headercontent));
390 Py_INCREF(Py_None);
391 return Py_None;
394 static PyObject* ComposeWindow_add_header(clawsmail_ComposeWindowObject *self, PyObject *args)
396 const char *header;
397 const char *text;
398 gint num;
400 if(!PyArg_ParseTuple(args, "ss", &header, &text))
401 return NULL;
403 /* add a dummy, and modify it then */
404 compose_entry_append(self->compose, "dummy1dummy2dummy3", COMPOSE_TO, PREF_NONE);
405 num = g_slist_length(self->compose->header_list);
406 if(num > 1) {
407 ComposeHeaderEntry *headerentry;
408 headerentry = g_slist_nth_data(self->compose->header_list, num-2);
409 if(headerentry) {
410 GtkEditable *editable;
411 gint pos;
412 gtk_entry_set_text(GTK_ENTRY(headerentry->entry), text);
413 editable = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(headerentry->combo)));
414 gtk_editable_delete_text(editable, 0, -1);
415 gtk_editable_insert_text(editable, header, -1, &pos);
419 flush_gtk_queue();
421 Py_INCREF(Py_None);
422 return Py_None;
425 static PyObject* ComposeWindow_get_account_selection(clawsmail_ComposeWindowObject *self, PyObject *args)
427 if(GTK_IS_COMBO_BOX(self->compose->account_combo))
428 return get_gobj_from_address(self->compose->account_combo);
430 Py_INCREF(Py_None);
431 return Py_None;
434 static PyObject* ComposeWindow_save_message_to(clawsmail_ComposeWindowObject *self, PyObject *args)
436 PyObject *arg;
438 if(!PyArg_ParseTuple(args, "O", &arg))
439 return NULL;
441 if(PyBytes_Check(arg)) {
442 GtkEditable *editable;
443 gint pos;
445 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->compose->savemsg_checkbtn), TRUE);
447 editable = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(self->compose->savemsg_combo)));
448 gtk_editable_delete_text(editable, 0, -1);
449 gtk_editable_insert_text(editable, PyBytes_AsString(arg), -1, &pos);
451 else if(clawsmail_folder_check(arg)) {
452 GtkEditable *editable;
453 gint pos;
455 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->compose->savemsg_checkbtn), TRUE);
457 editable = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(self->compose->savemsg_combo)));
458 gtk_editable_delete_text(editable, 0, -1);
459 gtk_editable_insert_text(editable, folder_item_get_identifier(clawsmail_folder_get_item(arg)), -1, &pos);
461 else if (arg == Py_None){
462 /* turn off checkbutton */
463 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->compose->savemsg_checkbtn), FALSE);
465 else {
466 PyErr_SetString(PyExc_TypeError, "function takes exactly one argument which may be a folder object, a string, or None");
467 return NULL;
470 flush_gtk_queue();
472 Py_INCREF(Py_None);
473 return Py_None;
476 static PyObject* ComposeWindow_set_modified(clawsmail_ComposeWindowObject *self, PyObject *args)
478 char modified = 0;
479 gboolean old_modified;
481 if(!PyArg_ParseTuple(args, "b", &modified))
482 return NULL;
484 old_modified = self->compose->modified;
486 self->compose->modified = (modified != 0);
488 /* If the modified state changed, rewrite window title.
489 * This partly duplicates functionality in compose.c::compose_set_title().
490 * While it's nice to not have to modify Claws Mail for this to work,
491 * it would be cleaner to export that function in Claws Mail. */
492 if((strcmp(gtk_window_get_title(GTK_WINDOW(self->compose->window)), _("Compose message")) != 0) &&
493 (old_modified != self->compose->modified)) {
494 gchar *str;
495 gchar *edited;
496 gchar *subject;
498 edited = self->compose->modified ? _(" [Edited]") : "";
499 subject = gtk_editable_get_chars(GTK_EDITABLE(self->compose->subject_entry), 0, -1);
500 if(subject && strlen(subject))
501 str = g_strdup_printf(_("%s - Compose message%s"),
502 subject, edited);
503 else
504 str = g_strdup_printf(_("[no subject] - Compose message%s"), edited);
505 gtk_window_set_title(GTK_WINDOW(self->compose->window), str);
506 g_free(str);
507 g_free(subject);
510 flush_gtk_queue();
512 Py_INCREF(Py_None);
513 return Py_None;
516 static PyObject* get_account(clawsmail_ComposeWindowObject *self, void *closure)
518 if(self->compose->account) {
519 return clawsmail_account_new(self->compose->account);
521 Py_RETURN_NONE;
524 static int set_account(clawsmail_ComposeWindowObject *self, PyObject *value, void *closure)
526 PrefsAccount *target_account;
528 if(value == NULL) {
529 PyErr_SetString(PyExc_TypeError, "Cannot delete 'account' attribute");
530 return -1;
533 if(!clawsmail_account_check(value)) {
534 PyErr_SetString(PyExc_TypeError, "ComposeWindow.account: Can only assign an account");
535 return -1;
539 target_account = clawsmail_account_get_account(value);
540 if(!target_account) {
541 PyErr_SetString(PyExc_TypeError, "Account value broken");
542 return -1;
545 if(!self->compose || !self->compose->account_combo) {
546 PyErr_SetString(PyExc_RuntimeError, "ComposeWindow: Cannot access account");
547 return -1;
550 combobox_select_by_data(GTK_COMBO_BOX(self->compose->account_combo), target_account->account_id);
552 return 0;
557 static PyMethodDef ComposeWindow_methods[] = {
558 {"set_subject", (PyCFunction)ComposeWindow_set_subject, METH_VARARGS,
559 "set_subject(text) - set subject to text\n"
560 "\n"
561 "Set the subject to text. text must be a string."},
563 {"get_subject", (PyCFunction)ComposeWindow_get_subject, METH_NOARGS,
564 "get_subject() - get subject\n"
565 "\n"
566 "Get a string of the current subject entry."},
568 {"set_from", (PyCFunction)ComposeWindow_set_from, METH_VARARGS,
569 "set_from(text) - set From header entry to text\n"
570 "\n"
571 "Set the From header entry to text. text must be a string.\n"
572 "Beware: No sanity checking is performed."},
574 {"get_from", (PyCFunction)ComposeWindow_get_from, METH_NOARGS,
575 "get_from - get From header entry\n"
576 "\n"
577 "Get a string of the current From header entry."},
579 {"add_To", (PyCFunction)ComposeWindow_add_To, METH_VARARGS,
580 "add_To(text) - append another To header with text\n"
581 "\n"
582 "Add another header line with the combo box set to To:, and the\n"
583 "content set to text."},
585 {"add_Cc", (PyCFunction)ComposeWindow_add_Cc, METH_VARARGS,
586 "add_Cc(text) - append another Cc header with text\n"
587 "\n"
588 "Add another header line with the combo box set to Cc:, and the\n"
589 "content set to text."},
591 {"add_Bcc", (PyCFunction)ComposeWindow_add_Bcc, METH_VARARGS,
592 "add_Bcc(text) - append another Bcc header with text\n"
593 "\n"
594 "Add another header line with the combo box set to Bcc:, and the\n"
595 "content set to text."},
597 {"add_header", (PyCFunction)ComposeWindow_add_header, METH_VARARGS,
598 "add_header(headername, text) - add a custom header\n"
599 "\n"
600 "Adds a custom header with the header set to headername, and the\n"
601 "contents set to text."},
603 {"get_header_list", (PyCFunction)ComposeWindow_get_header_list, METH_NOARGS,
604 "get_header_list() - get list of headers\n"
605 "\n"
606 "Gets a list of headers that are currently defined in the compose window.\n"
607 "The return value is a list of tuples, where the first tuple element is\n"
608 "the header name (entry in the combo box) and the second element is the contents."},
610 {"set_header_list", (PyCFunction)ComposeWindow_set_header_list, METH_VARARGS,
611 "set_header_list(list_of_header_value_pairs) - set list of headers\n"
612 "\n"
613 "Sets the list of headers that are currently defined in the compose window.\n"
614 "This function overwrites the current setting.\n\n"
615 "The parameter is expected to be a list of header name and value tuples,\n"
616 "analogous to the return value of the get_header_list() function."},
618 {"attach", (PyCFunction)ComposeWindow_attach, METH_VARARGS,
619 "attach(filenames) - attach a list of files\n"
620 "\n"
621 "Attach files to the mail. The filenames argument is a list of\n"
622 "string of the filenames that are being attached."},
624 {"get_account_selection", (PyCFunction)ComposeWindow_get_account_selection, METH_NOARGS,
625 "get_account_selection() - get account selection widget\n"
626 "\n"
627 "Returns the account selection combo box as a gtk.ComboBox"},
629 {"save_message_to", (PyCFunction)ComposeWindow_save_message_to, METH_VARARGS,
630 "save_message_to(folder) - save message to folder id\n"
631 "\n"
632 "Set the folder where the sent message will be saved to. folder may be\n"
633 "a Folder, a string of the folder identifier (e.g. #mh/foo/bar), or\n"
634 "None is which case the message will not be saved at all."},
636 {"set_modified", (PyCFunction)ComposeWindow_set_modified, METH_VARARGS,
637 "set_modified(bool) - set or unset modification marker of compose window\n"
638 "\n"
639 "Set or unset the modification marker of the compose window. This marker determines\n"
640 "for example whether you get a confirmation dialog when closing the compose window\n"
641 "or not.\n"
642 "In the usual case, Claws Mail keeps track of the modification status itself.\n"
643 "However, there are cases when it might be desirable to overwrite the marker,\n"
644 "for example because a compose_any script modifies the body or subject which\n"
645 "can be regarded compose window preprocessing and should not trigger a confirmation\n"
646 "dialog on close like a manual edit."},
648 {NULL}
651 static PyMemberDef ComposeWindow_members[] = {
652 {"ui_manager", T_OBJECT_EX, offsetof(clawsmail_ComposeWindowObject, ui_manager), 0,
653 "ui_manager - the gtk.UIManager of the compose window"},
655 {"text", T_OBJECT_EX, offsetof(clawsmail_ComposeWindowObject, text), 0,
656 "text - the gtk.TextView widget of the message body"},
658 {"replyinfo", T_OBJECT_EX, offsetof(clawsmail_ComposeWindowObject, replyinfo), 0,
659 "replyinfo - The MessageInfo object of the message that is being replied to, or None"},
661 {"forwardinfo", T_OBJECT_EX, offsetof(clawsmail_ComposeWindowObject, fwdinfo), 0,
662 "forwardinfo - The MessageInfo object of the message that is being forwarded, or None"},
664 {NULL}
667 static PyGetSetDef ComposeWindow_getset[] = {
668 {"account", (getter)get_account, (setter)set_account,
669 "account - the account corresponding to this compose window", NULL},
671 {NULL}
674 static PyTypeObject clawsmail_ComposeWindowType = {
675 PyVarObject_HEAD_INIT(NULL, 0)
676 "clawsmail.ComposeWindow", /*tp_name*/
677 sizeof(clawsmail_ComposeWindowObject), /*tp_basicsize*/
678 0, /*tp_itemsize*/
679 (destructor)ComposeWindow_dealloc, /*tp_dealloc*/
680 0, /*tp_print*/
681 0, /*tp_getattr*/
682 0, /*tp_setattr*/
683 0, /*tp_compare*/
684 0, /*tp_repr*/
685 0, /*tp_as_number*/
686 0, /*tp_as_sequence*/
687 0, /*tp_as_mapping*/
688 0, /*tp_hash */
689 0, /*tp_call*/
690 0, /*tp_str*/
691 0, /*tp_getattro*/
692 0, /*tp_setattro*/
693 0, /*tp_as_buffer*/
694 Py_TPFLAGS_DEFAULT, /*tp_flags*/
695 /* tp_doc */
696 "ComposeWindow objects. Optional argument to constructor: sender account address. ",
697 0, /* tp_traverse */
698 0, /* tp_clear */
699 0, /* tp_richcompare */
700 0, /* tp_weaklistoffset */
701 0, /* tp_iter */
702 0, /* tp_iternext */
703 ComposeWindow_methods, /* tp_methods */
704 ComposeWindow_members, /* tp_members */
705 ComposeWindow_getset, /* tp_getset */
706 0, /* tp_base */
707 0, /* tp_dict */
708 0, /* tp_descr_get */
709 0, /* tp_descr_set */
710 0, /* tp_dictoffset */
711 (initproc)ComposeWindow_init, /* tp_init */
712 0, /* tp_alloc */
713 0, /* tp_new */
714 0, /* tp_free */
715 0, /* tp_is_gc */
716 0, /* tp_bases */
717 0, /* tp_mro */
718 0, /* tp_cache */
719 0, /* tp_subclasses */
720 0, /* tp_weaklist */
721 0, /* tp_del */
722 #if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6) || \
723 (PY_MAJOR_VERSION == 3))
724 0, /* tp_version_tag */
725 #endif
726 #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4)
727 0, /* tp_finalize */
728 #endif
731 gboolean cmpy_add_composewindow(PyObject *module)
733 clawsmail_ComposeWindowType.tp_new = PyType_GenericNew;
734 if(PyType_Ready(&clawsmail_ComposeWindowType) < 0)
735 return FALSE;
737 Py_INCREF(&clawsmail_ComposeWindowType);
738 return (PyModule_AddObject(module, "ComposeWindow", (PyObject*)&clawsmail_ComposeWindowType) == 0);
741 PyObject* clawsmail_compose_new(PyObject *module, Compose *compose)
743 PyObject *class, *dict;
744 PyObject *self, *args, *kw;
746 if(!compose) {
747 Py_INCREF(Py_None);
748 return Py_None;
751 dict = PyModule_GetDict(module);
752 class = PyDict_GetItemString(dict, "ComposeWindow");
753 args = Py_BuildValue("()");
754 kw = Py_BuildValue("{s:b}", "__open_window", 0);
755 self = PyObject_Call(class, args, kw);
756 Py_DECREF(args);
757 Py_DECREF(kw);
758 composewindow_set_compose((clawsmail_ComposeWindowObject*)self, compose);
759 return self;