Subversion Repositories Scribus

Rev

Rev 418 | Rev 421 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
413 Franz 1
#include <Python.h>
2
#include <structmember.h>
420 Franz 3
#include <qfileinfo.h>
413 Franz 4
 
5
#include "cmdvar.h"
6
#include "cmdutil.h"
7
#include "objprinter.h"
8
#include <vector>
9
 
10
#ifdef HAVE_CUPS
11
#include <cups/cups.h>
12
#endif
13
#ifdef HAVE_CMS
14
extern bool CMSuse;
15
#endif
16
// these functions are located at utils.cpp
418 Franz 17
bool loadText(QString nam, QString *Buffer);
18
void ReOrderText(ScribusDoc *doc, ScribusView *view);
413 Franz 19
// end of utils.cpp
20
 
21
typedef struct
22
{
418 Franz 23
        PyObject_HEAD
24
        PyObject *allPrinters; // list of strings - names of installed printers
25
        PyObject *printer;  // string - selected printer
26
        PyObject *file;  // string - name of file to print into (eg. output.ps)
27
        PyObject *cmd; // string - if "" use standard command else use this as command (eg. "kprinter", "xpp" ...)
28
        PyObject *pages; // list of integers - pages to be printed
29
        int copies; // numer of printed copies    
30
        PyObject *separation; // string - No; All; Cyan; Magenta; Yellow; Black
31
        int color; // bool - do we print in color=1 or greyscale=0
32
        int useICC; // bool - do we use ICC Profiles 0 = No 1 = Yes
33
        int pslevel; // integer - 1, 2 or 3 level of used postscript
34
        int mph; // bool - mirror pages horizontally
35
        int mpv; // bool - mirror pages vertically
36
        int ucr; // bool - Under Color Removal
413 Franz 37
} Printer;
38
 
39
 
40
static void Printer_dealloc(Printer* self)
41
{
418 Franz 42
        Py_XDECREF(self->allPrinters);
43
        Py_XDECREF(self->printer);
44
        Py_XDECREF(self->file);
45
        Py_XDECREF(self->cmd);
46
        Py_XDECREF(self->pages);
47
        Py_XDECREF(self->separation);
48
        self->ob_type->tp_free((PyObject *)self);
413 Franz 49
}
50
 
51
static PyObject * Printer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
52
{
53
// do not create new object if there is no opened document
418 Franz 54
        if (!Carrier->HaveDoc) {
55
                PyErr_SetString(PyExc_SystemError, "Need to open document first");
56
                return NULL;
57
        }
413 Franz 58
 
418 Franz 59
        Printer *self;
60
        self = (Printer *)type->tp_alloc(type, 0);
61
        if (self != NULL) {
413 Franz 62
// set allPrinters attribute
418 Franz 63
                self->allPrinters = PyList_New(0);
64
                if (self->allPrinters == NULL){
65
                        Py_DECREF(self);
66
                        return NULL;
67
                }
413 Franz 68
// set printer attribute
418 Franz 69
                self->printer = PyString_FromString("");
70
                if (self->printer == NULL){
71
                        Py_DECREF(self);
72
                        return NULL;
73
                }
413 Franz 74
// set file attribute
418 Franz 75
                self->file = PyString_FromString("");
76
                if (self->file == NULL){
77
                        Py_DECREF(self);
78
                        return NULL;
79
                }
413 Franz 80
// set cmd attribute
418 Franz 81
                self->cmd = PyString_FromString("");
82
                if (self->cmd == NULL){
83
                        Py_DECREF(self);
84
                        return NULL;
85
                }
413 Franz 86
// set pages attribute
418 Franz 87
                self->pages = PyList_New(0);
88
                if (self->pages == NULL){
89
                        Py_DECREF(self);
90
                        return NULL;
91
                }
413 Franz 92
// set separation attribute
418 Franz 93
                self->separation = PyString_FromString("No");
94
                if (self->separation == NULL){
95
                        Py_DECREF(self);
96
                        return NULL;
97
                }
413 Franz 98
// set color attribute
418 Franz 99
                self->color = 1;
413 Franz 100
// set useICC attribute
418 Franz 101
                self->useICC = 0;
413 Franz 102
// set pslevel attribute
418 Franz 103
                self->pslevel = 3;
413 Franz 104
// set mph attribute
418 Franz 105
                self->mph = 0;
413 Franz 106
// set mpv attribute
418 Franz 107
                self->mpv = 0;
413 Franz 108
// set ucr attribute
418 Franz 109
                self->ucr = 1;
413 Franz 110
// set copies attribute
418 Franz 111
                self->copies = 1;
112
        }
113
        return (PyObject *) self;
413 Franz 114
}
115
 
116
static int Printer_init(Printer *self, PyObject *args, PyObject *kwds)
117
{
118
// pool system for installed printers
119
// most code is stolen and little adopted from druck.cpp
418 Franz 120
        PyObject *allPrinters = PyList_New(0);
121
        if (allPrinters){
122
                Py_DECREF(self->allPrinters);
123
                self->allPrinters = allPrinters;
124
        }
413 Franz 125
#ifdef HAVE_CUPS
418 Franz 126
        cups_dest_t *dests;
127
        int num_dests = cupsGetDests(&dests);
128
        for (int i = 0; i < num_dests; ++i) {
129
                if (dests[i].name != NULL) {
130
                        PyObject *tmp = PyString_FromString(dests[i].name);
420 Franz 131
                        if (tmp) {
418 Franz 132
                                PyList_Append(self->allPrinters, tmp);
420 Franz 133
                                Py_DECREF(tmp);
134
                        }
418 Franz 135
                }
413 Franz 136
        }
418 Franz 137
        cupsFreeDests(num_dests, dests);
413 Franz 138
#else
418 Franz 139
        QString Pcap;
413 Franz 140
        // loadText is defined in utils.cpp
418 Franz 141
        if (loadText("/etc/printcap", &Pcap))
413 Franz 142
        {
418 Franz 143
                QTextStream ts(&Pcap, IO_ReadOnly);
144
                while(!ts.atEnd())
145
                {
146
                        QStringList wt;
147
                        QString tmp = ts.readLine();
148
                        if (tmp.isEmpty())
149
                                continue;
150
                        if ((tmp[0] != '#') && (tmp[0] != ' ') && (tmp[0] != '\n') && (tmp[0] != '\t'))
151
                        {
152
                                tmp = tmp.stripWhiteSpace();
153
                                tmp = tmp.left(tmp.length() - (tmp.right(2) == ":\\" ? 2 : 1));
154
                                wt = QStringList::split("|", tmp);
155
                                PyObject *tmppr = PyString_FromString(wt[0]);
156
                                if (tmppr){
157
                                        PyList_Append(self->allPrinters, tmppr);
420 Franz 158
                                        Py_DECREF(tmppr);
418 Franz 159
                                }
160
                        }
413 Franz 161
                }
162
        }
163
#endif
420 Franz 164
        PyObject *tmp2 = PyString_FromString("File");
165
        PyList_Append(self->allPrinters, tmp2);
166
        Py_DECREF(tmp2);
413 Franz 167
// as defaut set to print into file
418 Franz 168
        PyObject *printer = NULL;
169
        printer = PyString_FromString("File");
170
        if (printer){
171
                Py_DECREF(self->printer);
172
                self->printer = printer;
173
        }
413 Franz 174
// set defaul name of file to print into
420 Franz 175
        QString tf = Carrier->doc->PDF_Optionen.Datei;
176
        if (tf == "") {
177
                QFileInfo fi = QFileInfo(Carrier->doc->DocName);
178
                tf = fi.dirPath()+"/"+fi.baseName()+".pdf";
179
        }
418 Franz 180
        PyObject *file = NULL;
420 Franz 181
        file = PyString_FromString(tf.ascii());
418 Franz 182
        if (file){
183
                Py_DECREF(self->file);
184
                self->file = file;
420 Franz 185
        } else {
186
                PyErr_SetString(PyExc_SystemError, "Can not initialize 'file' attribute");
187
                return -1;
418 Franz 188
        }
413 Franz 189
// alternative printer commands default to ""
418 Franz 190
        PyObject *cmd = NULL;
191
        cmd = PyString_FromString("");
192
        if (cmd){
193
                Py_DECREF(self->cmd);
194
                self->cmd = cmd;
195
        }
413 Franz 196
// if document exist when created Printer instance
197
// set to print all pages
418 Franz 198
        PyObject *pages = NULL;
199
        int num = 0;
200
        if (Carrier->HaveDoc)
201
                // which one should I use ???
202
                // new = Carrier->view->Pages.count()
203
                num = Carrier->doc->PageC;
204
        pages = PyList_New(num);
205
        if (pages){
206
                Py_DECREF(self->pages);
207
                self->pages = pages;
208
        }
209
        for (int i = 0; i<num; i++) {
210
                PyObject *tmp=NULL;
211
                tmp = PyInt_FromLong((long)i+1L); // instead of 1 put here first page number
212
                if (tmp)
213
                        PyList_SetItem(self->pages, i, tmp);
214
        }
413 Franz 215
// do not print separation
418 Franz 216
        PyObject *separation = NULL;
217
        separation = PyString_FromString("No");
218
        if (separation){
219
                Py_DECREF(self->separation);
220
                self->separation = separation;
221
        }
413 Franz 222
// print in color
418 Franz 223
        self->color = 1;
413 Franz 224
// do not use ICC Profile
418 Franz 225
        self->useICC = 0;
413 Franz 226
// use PostScrip level 3
418 Franz 227
        self->pslevel = 3;
413 Franz 228
// do not mirror pages
418 Franz 229
        self->mph = 0;
413 Franz 230
// do not mirror pages
418 Franz 231
        self->mpv = 0;
413 Franz 232
// apply Under Color Removal as default
418 Franz 233
        self->ucr = 1;
413 Franz 234
// number of copies
418 Franz 235
        self->copies = 1;
236
        return 0;
413 Franz 237
}
238
 
239
static PyMemberDef Printer_members[] = {
418 Franz 240
        {"copies", T_INT, offsetof(Printer, copies), 0, "Number of copies"},
241
        {"color", T_INT, offsetof(Printer, color), 0, "Print in color.\n\t True - color  --  Default\n\t False - greyscale"},
242
        {"useICC", T_INT, offsetof(Printer, useICC), 0, "Use ICC Profile\n\tTrue\n\tFalse  --  Default"},
243
        {"pslevel", T_INT, offsetof(Printer, pslevel), 0, "PostScript Level\nCan be 1 or 2 or 3    -- Default is 3."},
244
        {"mph", T_INT, offsetof(Printer, mph), 0, "Mirror Pages Horizontal\n\tTrue\n\tFalse  --  Default"},
245
        {"mpv", T_INT, offsetof(Printer, mpv), 0, "Mirror Pages Vertical\n\t True\n\tFalse  --  Default"},
246
        {"ucr", T_INT, offsetof(Printer, ucr), 0, "Apply Under Color Removal\n\tTrue  --  Default\n\tFalse"},
247
        {NULL}                      // sentinel
413 Franz 248
};
249
 
250
/* Here begins Getter & Setter functions */
251
 
252
static PyObject *Printer_getallPrinters(Printer *self, void *closure)
253
{
418 Franz 254
        Py_INCREF(self->allPrinters);
255
        return self->allPrinters;
413 Franz 256
}
257
 
258
static int Printer_setallPrinters(Printer *self, PyObject *value, void *closure)
259
{
418 Franz 260
        PyErr_SetString(PyExc_ValueError, "'allPrinters' attribute is READ-ONLY");
261
        return -1;
413 Franz 262
}
263
 
264
static PyObject *Printer_getprinter(Printer *self, void *closure)
265
{
418 Franz 266
        Py_INCREF(self->printer);
267
        return self->printer;
413 Franz 268
}
269
 
270
static int Printer_setprinter(Printer *self, PyObject *value, void *closure)
271
{
418 Franz 272
        if (value == NULL) {
273
                PyErr_SetString(PyExc_TypeError, "Cannot delete 'printer' attribute.");
274
                return -1;
275
        }
276
        if (!PyString_Check(value)) {
277
                PyErr_SetString(PyExc_TypeError, "The 'printer' attribute value must be string.");
278
                return -1;
279
        }
280
        int n = PyList_Size(self->allPrinters);
281
        bool same = 0;
282
        for (int i = 0; i<n; i++)
283
                if (PyObject_RichCompareBool(value, PyList_GetItem(self->allPrinters, i), Py_EQ) == 1)
284
                        same = true;
285
        if (!same) {
286
                PyErr_SetString(PyExc_ValueError, "'printer' value can be only one of string in 'allPrinters' attribute ");
287
                return -1;
288
        }
289
        Py_DECREF(self->printer);
290
        Py_INCREF(value);
291
        self->printer = value;
292
        return 0;
413 Franz 293
}
294
 
295
static PyObject *Printer_getfile(Printer *self, void *closure)
296
{
418 Franz 297
        Py_INCREF(self->file);
298
        return self->file;
413 Franz 299
}
300
 
301
static int Printer_setfile(Printer *self, PyObject *value, void *closure)
302
{
418 Franz 303
        if (value == NULL) {
304
                PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
305
                return -1;
306
        }
307
        if (!PyString_Check(value)) {
308
                PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
309
                return -1;
310
        }
311
        Py_DECREF(self->file);
312
        Py_INCREF(value);
313
        self->file = value;
314
        return 0;
413 Franz 315
}
316
 
317
static PyObject *Printer_getcmd(Printer *self, void *closure)
318
{
418 Franz 319
        Py_INCREF(self->cmd);
320
        return self->cmd;
413 Franz 321
}
322
 
323
static int Printer_setcmd(Printer *self, PyObject *value, void *closure)
324
{
418 Franz 325
        if (value == NULL) {
326
                PyErr_SetString(PyExc_TypeError, "Cannot delete 'cmd' attribute.");
327
                return -1;
328
        }
329
        if (!PyString_Check(value)) {
330
                PyErr_SetString(PyExc_TypeError, "The 'cmd' attribute value must be string.");
331
                return -1;
332
        }
333
        Py_DECREF(self->cmd);
334
        Py_INCREF(value);
335
        self->cmd = value;
336
        return 0;
413 Franz 337
}
338
 
339
static PyObject *Printer_getpages(Printer *self, void *closure)
340
{
418 Franz 341
        Py_INCREF(self->pages);
342
        return self->pages;
413 Franz 343
}
344
 
345
static int Printer_setpages(Printer *self, PyObject *value, void *closure)
346
{
418 Franz 347
        if (value == NULL) {
348
                PyErr_SetString(PyExc_TypeError, "Cannot delete 'pages' attribute.");
349
                return -1;
413 Franz 350
        }
418 Franz 351
        if (!PyList_Check(value)) {
352
                PyErr_SetString(PyExc_TypeError, "'pages' attribute value must be list of integers.");
353
                return -1;
354
        }
355
        int len = PyList_Size(value);
356
        for (int i = 0; i<len; i++){
357
                PyObject *tmp = PyList_GetItem(value, i);
358
                if (!PyInt_Check(tmp)){
359
                        PyErr_SetString(PyExc_TypeError, "'pages' attribute must be list containing only integers.");
360
                        return -1;
361
                }
420 Franz 362
                if (PyInt_AsLong(tmp) > Carrier->doc->PageC || PyInt_AsLong(tmp) < 1) {
363
                        PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
364
                        return -1;
365
                }      
418 Franz 366
        }
367
        Py_DECREF(self->pages);
368
        Py_INCREF(value);
369
        self->pages = value;
370
        return 0;
413 Franz 371
}
372
 
373
static PyObject *Printer_getseparation(Printer *self, void *closure)
374
{
418 Franz 375
        Py_INCREF(self->separation);
376
        return self->separation;
413 Franz 377
}
378
 
379
static int Printer_setseparation(Printer *self, PyObject *value, void *closure)
380
{
418 Franz 381
        if (value == NULL) {
382
                PyErr_SetString(PyExc_TypeError, "Cannot delete 'separation' attribute.");
383
                return -1;
384
        }
385
        if (!PyString_Check(value)) {
386
                PyErr_SetString(PyExc_TypeError, "The 'separation' attribute value must be string.");
387
                return -1;
388
        }
389
        Py_DECREF(self->separation);
390
        Py_INCREF(value);
391
        self->separation = value;
392
        return 0;
413 Franz 393
}
394
 
395
 
396
static PyGetSetDef Printer_getseters [] = {
418 Franz 397
        {"allPrinters", (getter)Printer_getallPrinters, (setter)Printer_setallPrinters, "List of installed printers  --  read only", NULL},
398
        {"printer", (getter)Printer_getprinter, (setter)Printer_setprinter, "Name of printer to use.\nDefault is 'File' for printing into file", NULL},
399
        {"file", (getter)Printer_getfile, (setter)Printer_setfile, "Name of file to print into", NULL},
400
        {"cmd", (getter)Printer_getcmd, (setter)Printer_setcmd, "Alternative Printer Command", NULL},
401
        {"pages", (getter)Printer_getpages, (setter)Printer_setpages, "List of pages to be printed", NULL},
402
        {"separation", (getter)Printer_getseparation, (setter)Printer_setseparation, "Print separationl\n\t 'No'  -- Default\n\t 'All'\n\t 'Cyan'\n\t 'Magenta'\n\t 'Yellow'\n\t 'Black'\nBeware of misspelling because check is not performed", NULL},
403
        {NULL}  // sentinel
413 Franz 404
};
405
 
406
// Here we actually print 
407
static PyObject *Printer_print(Printer *self)
408
{
418 Franz 409
        if (!Carrier->HaveDoc) {
410
                PyErr_SetString(PyExc_SystemError, "Need to open documetnt first");
411
                return NULL;
412
        }
413 Franz 413
// copied from void ScribusApp::slotFilePrint() in file scribus.cpp
418 Franz 414
        QString fna, prn, cmd, scmd, cc, data, SepName;
415
        QString printcomm;
416
        int Nr, PSLevel;
417
        bool fil, sep, color, PSfile, mirrorH, mirrorV, useICC, DoGCR;
418
        PSfile = false;
413 Franz 419
 
420
//    ReOrderText(Carrier->doc, Carrier->view);
418 Franz 421
        prn = QString(PyString_AsString(self->printer));
422
        fna = QString(PyString_AsString(self->file));
423
        fil = (QString(PyString_AsString(self->printer)) == QString("File")) ? true : false;
424
        std::vector<int> pageNs;
425
        for (int i = 0; i < PyList_Size(self->pages); ++i) {
426
                pageNs.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
427
        }
428
        Nr = (self->copies < 1) ? 1 : self->copies;
429
        SepName = QString(PyString_AsString(self->separation));
430
        sep =(SepName == QString("No")) ?  false : true;
420 Franz 431
//         if (SepName == QString("All"))
432
//                 SepName = tr(SepName);
433
        color = self->color;
434
        mirrorH = self->mph;
435
        mirrorV = self->mpv;
436
        useICC = self->useICC;
437
        DoGCR = self->ucr;
418 Franz 438
        int psl = self->pslevel;
439
        if (psl < 1)
440
                psl = 1;
441
        else if (psl > 3)
442
                psl = 3;
443
        PSLevel = psl;
444
        printcomm = QString(PyString_AsString(self->cmd));
445
        QMap<QString,QFont> ReallyUsed;
446
        ReallyUsed.clear();
447
        Carrier->GetUsedFonts(&ReallyUsed);
448
        PSLib *dd = Carrier->getPSDriver(true, Carrier->Prefs.AvailFonts, ReallyUsed, Carrier->doc->PageColors, false);
449
        if (dd != NULL)
413 Franz 450
        {
418 Franz 451
                if (!fil)
452
                        fna = Carrier->PrefsPfad+"/tmp.ps";
453
                PSfile = dd->PS_set_file(fna);
454
                if (PSfile)
413 Franz 455
                {
418 Franz 456
                        Carrier->view->CreatePS(dd, pageNs, sep, SepName, color, mirrorH, mirrorV, useICC, DoGCR);
457
                        if (PSLevel != 3)
458
                        {
459
                                QString tmp;
460
                                QString opts = "-dDEVICEWIDTHPOINTS=";
461
                                opts += tmp.setNum(Carrier->doc->PageB);
462
                                opts += " -dDEVICEHEIGHTPOINTS=";
463
                                opts += tmp.setNum(Carrier->doc->PageH);
464
                                if (PSLevel == 1)
465
                                        system("ps2ps -dLanguageLevel=1 "+opts+" \""+fna+"\" \""+fna+".tmp\"");
466
                                else
467
                                        system("ps2ps "+opts+" \""+fna+"\" \""+fna+".tmp\"");
468
                                system("mv \""+fna+".tmp\" \""+fna+"\"");
469
                        }
470
 
471
                        if (!fil)
472
                        {
473
                                if (printcomm != "")
474
                                        cmd = printcomm + " "+fna;
475
                                else
476
                                {
477
                                        cmd = "lpr -P" + prn;
478
                                        if (Nr > 1)
479
                                                cmd += " -#" + cc.setNum(Nr);
413 Franz 480
#ifdef HAVE_CUPS
418 Franz 481
// This need yet to be implemented by object Printer
482
//                                        cmd += printer->PrinterOpts;
413 Franz 483
#endif
418 Franz 484
                                        cmd += " "+fna;
485
                                }
486
                                system(cmd);
487
                                unlink(fna);
488
                        }
413 Franz 489
                }
418 Franz 490
                else {
491
                        delete dd;
492
                        Carrier->closePSDriver();
493
                        PyErr_SetString(PyExc_SystemError, "Printing failed");
494
                        return NULL;
495
                }
496
                delete dd;
497
                Carrier->closePSDriver();
413 Franz 498
        }
418 Franz 499
        Py_INCREF(Py_None);
500
        return Py_None;
413 Franz 501
}
502
 
503
static PyMethodDef Printer_methods[] = {
418 Franz 504
        {"Print", (PyCFunction)Printer_print, METH_NOARGS, "Prints selected pages."},
505
        {NULL} // sentinel
413 Franz 506
};
507
 
508
PyTypeObject Printer_Type = {
418 Franz 509
        PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD 
510
        0,                         // 
511
        "Printer", // char *tp_name; /* For printing, in format "<module>.<name>" */
512
        sizeof(Printer),   // int tp_basicsize, /* For allocation */
513
        0,                       // int tp_itemsize; /* For allocation */
413 Franz 514
 
515
        /* Methods to implement standard operations */
516
 
418 Franz 517
        (destructor) Printer_dealloc, //     destructor tp_dealloc;
518
        0, //     printfunc tp_print;
519
        0, //     getattrfunc tp_getattr;
520
        0, //     setattrfunc tp_setattr;
521
        0, //     cmpfunc tp_compare;
522
        0, //     reprfunc tp_repr;
413 Franz 523
 
524
        /* Method suites for standard classes */
525
 
418 Franz 526
        0, //     PyNumberMethods *tp_as_number;
527
        0, //     PySequenceMethods *tp_as_sequence;
528
        0, //     PyMappingMethods *tp_as_mapping;
413 Franz 529
 
530
        /* More standard operations (here for binary compatibility) */
531
 
418 Franz 532
        0, //     hashfunc tp_hash;
533
        0, //     ternaryfunc tp_call;
534
        0, //     reprfunc tp_str;
535
        0, //     getattrofunc tp_getattro;
536
        0, //     setattrofunc tp_setattro;
413 Franz 537
 
538
        /* Functions to access object as input/output buffer */
418 Franz 539
        0, //     PyBufferProcs *tp_as_buffer;
413 Franz 540
 
541
        /* Flags to define presence of optional/expanded features */
418 Franz 542
        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,    // long tp_flags;
413 Franz 543
 
418 Franz 544
        "Printer Object",      // char *tp_doc; /* Documentation string */
413 Franz 545
 
546
        /* Assigned meaning in release 2.0 */
547
        /* call function for all accessible objects */
418 Franz 548
        0, //     traverseproc tp_traverse;
413 Franz 549
 
550
        /* delete references to contained objects */
418 Franz 551
        0, //     inquiry tp_clear;
413 Franz 552
 
553
        /* Assigned meaning in release 2.1 */
554
        /* rich comparisons */
418 Franz 555
        0, //     richcmpfunc tp_richcompare;
413 Franz 556
 
557
        /* weak reference enabler */
418 Franz 558
        0, //     long tp_weaklistoffset;
413 Franz 559
 
560
        /* Added in release 2.2 */
561
        /* Iterators */
418 Franz 562
        0, //     getiterfunc tp_iter;
563
        0, //     iternextfunc tp_iternext;
413 Franz 564
 
565
        /* Attribute descriptor and subclassing stuff */
418 Franz 566
        Printer_methods, //     struct PyMethodDef *tp_methods;
567
        Printer_members, //     struct PyMemberDef *tp_members;
568
        Printer_getseters, //     struct PyGetSetDef *tp_getset;
569
        0, //     struct _typeobject *tp_base;
570
        0, //     PyObject *tp_dict;
571
        0, //     descrgetfunc tp_descr_get;
572
        0, //     descrsetfunc tp_descr_set;
573
        0, //     long tp_dictoffset;
574
        (initproc)Printer_init, //     initproc tp_init;
575
        0, //     allocfunc tp_alloc;
576
        Printer_new, //     newfunc tp_new;
577
        0, //     freefunc tp_free; /* Low-level free-memory routine */
578
        0, //     inquiry tp_is_gc; /* For PyObject_IS_GC */
579
        0, //     PyObject *tp_bases;
580
        0, //     PyObject *tp_mro; /* method resolution order */
581
        0, //     PyObject *tp_cache;
582
        0, //     PyObject *tp_subclasses;
583
        0, //     PyObject *tp_weaklist;
584
        0, //     destructor tp_del;
413 Franz 585
 
586
#ifdef COUNT_ALLOCS
587
        /* these must be last and never explicitly initialized */
588
        //    int tp_allocs;
589
        //    int tp_frees;
590
        //    int tp_maxalloc;
591
        //    struct _typeobject *tp_next;
592
#endif
593
};