Commit d338b6e3 authored by Jack Jansen's avatar Jack Jansen

Removing the obvious OS9-only documents§

parent 28ecf70d
This diff is collapsed.
<HTML><HEAD><TITLE>Using python to create CGI scripts</TITLE></HEAD>
<BODY>
<H1>Using python to create CGI scripts</H1>
<HR>
In this document we will (eventually) explain how to create Python CGI scripts
for use with Personal WebServer, WebStar and probably other Mac-based HTTP servers too.
Since CGI scripts are AppleEvent servers on the mac we will also learn
a little about general AppleEvent server programming and about applet
debugging. <p>
<blockquote>Note that the current setup is very preliminary, and hence
itis probably not wise to base your strategic products on the information
in this document:-) In stead, play with the code here and join the
<a href="mailto:pythonmac-sig-request@python.org">pythonmac-sig</a>, where
we I would like to have a discussion on a real design for a Mac CGI framework
(preferrably something that will make CGI scripts portable to unix and other
platforms).
</blockquote>
<h2>AppleEvent servers</h2>
Since AppleEvent clients are easier to write and understand than servers
you should probably read the section on <a href="applescript.html">Open Scripting
clients in Python</a> first. <p>
Next, let us have a look at the AE Server framework,
<a href="../Lib/toolbox/MiniAEFrame.py">MiniAEFrame.py</a>.
This file contains two classes, <code>MiniApplication</code> and <code>AEServer</code>.
MiniApplication is a tiny replacement for <code>FrameWork.Application</code>,
suitable if your application does not need windows and such.
AEServer is a bit of glue that does part of the appleevent decoding for you. You
call <code>installaehandler</code> passing it the class and id (4-char strings)
of the event you have a handler for and the handler callback routine. When the
appleevent occurs your callback is called with the right arguments. For now,
your argument names are the 4-char values used internally by Open Scripting,
eventually there will be a translation similar to what the generated OSA client
suites provide. <p>
You can test AEServer by double-clicking it. It will react to the standard
run/open/print/quit OSA commands. If it is running as a normal python script and you
drag a file onto the interpreter the script will tell you what event it got. <p>
<h2>A Minimal CGI script</h2>
To try a CGI script you will first need a http server. Apple's Personal Webserver
is fine, but I have also used the
shareware
<a href="http://www.stairways.com/netpresenz/">NetPresenz</a>
by Peter Lewis
(don't forget to pay if you give it more than a test run!). Install your
http server, and make sure that it can serve textual documents. <p>
Next, let us have a look at our example CGI scripts. CGI scripts have to be
applications, so we will have to make an applet as explained in
<a href="example2.html">example 2</a>. Our applet code,
<a href="cgi/cgitest.cgi.py">cgitest.cgi.py</a> is a rather minimal <code>execfile</code>
statement. The reason for this is debugging: the real code is in
<a href="cgi/realcgitest.py">realcgitest.py</a>, and this way you do not have
to run mkapplet again every time you change the code. Rename realcgitest.py
to cgitest.cgi.py once you are satisfied that it works. <p>
The resource file is not very special, with one exception: since we want to do
our own appleevent handling we don't want the Python initialization code to
create argc and argv for use, since this might gobble up any appleevents we are
interested in. For this reason we have included a 'Popt' resource that disables
the argv initialization. An easy way to create this resource is to drop
the <code>.rsrc</code> file (or the finished applet, if you like) onto
<code>EditPythonPrefs</code> and set the "no argv processing" option. <p>
The code itself is actually not too complicated either. We install handlers
for "open application" and "quit" (stolen from the test code in MiniAEFrame)
and the <code>"WWW\275"/"sdoc"</code> event, the event sent on CGI execution.
The cgi handler pretty-prints the CGI arguments in HTML and returns the whole
string that is to be passed to the client. The actual parameters passed
are explained in <a href="http://www.biap.com/datapig/mrwheat/cgi_params.html">
http://www.biap.com/datapig/mrwheat/cgi_params.html</a>. <p>
To test the script drop <code>cgitest.cgi.py</code> onto <code>mkapplet</code>,
move the resulting <code>cgitest.cgi</code> to somewhere where it is reachable
by NetPresenz, and point your web browser towards it. Note that this assume you have
already renamed realcgitest.py to cgitest.cgi.py, otherwise you'll also have
to copy that file along. <p>
For Apple's Personal Webserver you need to do a bit more: you have to copy the
cgi applet to somewhere in your "Webpages" folder and you have to tell the webserver
(in the control panels) that your CGI script exists. I don't understand what the various
types of cgi scripts mean, but experiment with them.
</BODY></HTML>
# Debug applets quickly.
execfile('realcgitest.py')
"""cgitest - A minimal CGI applet. Echos parameters back to the client.
"""
from MiniAEFrame import AEServer, MiniApplication
import MacOS
debug=1
class CGITest(AEServer, MiniApplication):
def __init__(self):
MiniApplication.__init__(self)
AEServer.__init__(self)
self.installaehandler('aevt', 'oapp', self.open_app)
self.installaehandler('aevt', 'quit', self.quit)
self.installaehandler('WWW\275', 'sdoc', self.cgihandler)
if debug:
self.installaehandler('****', '****', self.otherhandler)
oldparams = MacOS.SchedParams(0, 0)
self.mainloop()
apply(MacOS.SchedParams, oldparams)
def quit(self, **args):
self.quitting = 1
def open_app(self, **args):
pass
def otherhandler(self, *args, **kwargs):
print 'Unknown AppleEvent'
print 'args', args
print 'kwargs', kwargs
def cgihandler(self, pathargs, **args):
if debug:
print 'CGI request', pathargs, args
rv = """HTTP/1.0 200 OK
Server: Unknown; python-cgi-script
MIME-Version: 1.0
Content-type: text/html
<title>Python CGI-script results</title>
<h1>Python CGI-script results</h1>
<hr>
"""
rv = rv+'<br><b>Direct object:</b> %s\n'%pathargs
for key in args.keys():
if key[0] != '_':
rv = rv + '<br><b>%s:</b> %s\n'%(key, args[key])
rv = rv +'<hr>\nSee you next time!\n'
# Note: if you want to quit after each request enable the line
# self.quitting = 1
return rv
if __name__ == '__main__':
CGITest()
<HTML>
<HEAD>
<TITLE>Embedding Python on the Mac</TITLE>
</HEAD>
<BODY>
<H1>Embedding Python on the Mac</H1>
<HR>
<B>Note</B>: if you have a binary-only release of MacPython you will not
have this demo installed. Install the developer option (in the standard installer) or
a source release if you want to embed
Python in other applications. <p>
Embedding Python on the mac is pretty similar to embedding it on other
platforms, but a few points need mentioning:
<UL>
<LI> You call <CODE>PyMac_Initialize()</CODE> in stead of
<CODE>Py_Initialize()</CODE>. The prototype is in <CODE>macglue.h</CODE>.
This call initializes the toolbox, GUSI (if needed), sets up the correct
resource files and calls Py_Initialize.
<LI> You have to be consequent in your use of GUSI. If the library uses
it so should your program and vice versa.
<LI> The console-behaviour (close-on-exit, etc) is controlled by Python
but you can overwrite this with <code>PyMac_SetConsoleHandler()</code>.
</UL>
The Python environment is started with a dummy argc and argv, and initial
startup options are obtained through the usual means, except that the
user pression the option-key will not result in an interactive dialog.
You can, however, set startup options on your program in the same way as you
do for applets, by dragging your application to <code>EditPythonPrefs</code>. <p>
The most logical way to embed Python is to link it against the shared
library <code>PythonCore</code>. An example project and source can be
found in the <a href="embed">embed</a> folder. <p>
This example code also shows how to override the console: if you pass the
<code>-q</code> argument in the argument box output is thrown away. If you
pass the <code>-d</code> option the output is sent to <code>DebugStr</code>
(so be sure to use this only when running the example under a debugger).
</BODY>
</HTML>
/* Example of embedding Python in another program */
#include "Python.h"
#include "macglue.h"
static char *argv0;
long my_writehandler(char *buf, long count)
{
long mycount;
unsigned char mybuf[255];
mycount = count;
if (mycount > 255 ) mycount = 255;
mybuf[0] = (unsigned char)mycount;
strncpy((char *)mybuf+1, buf, mycount);
DebugStr(mybuf);
return count;
}
main(argc, argv)
int argc;
char **argv;
{
/* So the user can set argc/argv to something interesting */
argc = ccommand(&argv);
/* Save a copy of argv0 */
argv0 = argv[0];
/* If the first option is "-q" we don't open a console */
if ( argc > 1 && strcmp(argv[1], "-q") == 0 ) {
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, PyMac_DummyWriteHandler,
PyMac_DummyWriteHandler);
} else
if ( argc > 1 && strcmp(argv[1], "-d") == 0 ) {
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, my_writehandler,
my_writehandler);
}
/* Initialize the Python interpreter. Required. */
PyMac_Initialize();
/* Define sys.argv. It is up to the application if you
want this; you can also let it undefined (since the Python
code is generally not a main program it has no business
touching sys.argv...) */
PySys_SetArgv(argc, argv);
/* Do some application specific code */
printf("Hello, brave new world\n\n");
/* Execute some Python statements (in module __main__) */
PyRun_SimpleString("import sys\n");
PyRun_SimpleString("print sys.builtin_module_names\n");
PyRun_SimpleString("print sys.argv\n");
/* Note that you can call any public function of the Python
interpreter here, e.g. call_object(). */
/* Some more application specific code */
printf("\nGoodbye, cruel world\n");
/* Exit, cleaning up the interpreter */
Py_Exit(0);
/*NOTREACHED*/
}
/* This function is called by the interpreter to get its own name */
char *
getprogramname()
{
return argv0;
}
<HTML>
<HEAD>
<TITLE>Creating standalone applications with Python</TITLE>
</HEAD>
<BODY>
<H1>Creating standalone applications with Python</H1>
With <a href="example2.html#applet">BuildApplet</a> you can build a standalone
Python application that works like
any other Mac application: you can double-click it, run it while the
Python interpreter is running other scripts, drop files on it, etc. It is, however,
still dependent on the whole Python installation on your machine: the PythonCore
engine, the plugin modules and the various Lib folders.<p>
In some cases you may want to create a true application, for instance because
you want to send it off to people who may not have Python installed on their
machine, or because you the application is important and you do not want changes
in your Python installation like new versions to influence it.
<H2>The easy way</H2>
The easiest way to create an application from a Python script is simply by dropping
it on the <code>BuildApplication</code> applet in the main Python folder.
BuildApplication has a similar interface as BuildApplet: you drop a script on
it and it will process it, along with an optional <code>.rsrc</code> file.
<P>
What BuildApplication does, however, is very different. It parses your script,
recursively looking for all modules you use, bundles the compiled code for
all these modules in PYC resources, adds the executable machine code for the
PythonCore engine, any dynamically loaded modules you use and a main program, combines
all this into a single file and adds a few preference resources (which you
can inspect with <code>EditPythonPrefs</code>, incidentally) to isolate the
new program from the existing Python installation.<P>
Usually you do not need to worry about all this, but occasionally you may have
to exercise some control over the process, for instance because your
program imports modules that don't exist (which can happen if your script
is multi-platform and those modules will never be used on the Mac). See
the section on <a href="#directives">directives</a> below for details.
If you get strange error messages about missing modules it may also be worthwhile
to run macfreeze in report mode on your program, see below.
<P>
<H2>Doing it the hard way</H2>
With the <EM>macfreeze</EM> script, for which BuildApplication is a simple
wrapper, you can go a step further and create CodeWarrior projects and
sourcefiles which can then be used to build your final application. While
BuildApplication is good enough for 90% of the use cases there are situations
where you need macfreeze itself, mainly if you want to embed your frozen Python
script into an existing C application, or when you need the extra bit of speed:
the resulting application will start up a bit quicker than one generated
with BuildApplication. <p>
When you start
<code>Mac:Tools:macfreeze:macfreeze.py</code> you are asked for the
script file, and you can select which type of freeze to do. The first
time you should always choose <em>report only</em>, which will produce a
listing of modules and where they are included from in the console
window. Macfreeze actually parses all modules, so it may crash in the
process. If it does try again with a higher debug value, this should
show you where it crashes. <p>
<h2><a name="directives">Directives</a></h2>
For more elaborate programs you will often see that freeze includes
modules you don't need (because they are for a different platform, for
instance) or that it cannot find all your modules (because you modify
<code>sys.path</code> early in your initialization). It is possible to
include directives to tell macfreeze to add items to the search path and
include or exclude certain modules. All your directives should be in the
main script file. <p>
Directives have the following form:
<pre>
# macfreeze: command argument
</pre>
The trigger <code>macfreeze:</code> must be spelled exactly like that,
but the whitespace can be any combination of spaces and tabs. Macfreeze
understands the following directives:
<DL>
<DT> <code>path</code>
<DD> Prepend a folder to <code>sys.path</code>. The argument is a
pathname, which should probably be relative (starting with a colon) and
is interpreted relative to the folder where the script lives.
<DT> <code>include</code>
<DD> Include a module. The module can either be given by filename or by
module name, in which case it is looked up through the normal method.
<DT> <code>exclude</code>
<DD> Exclude a module. The module must be given by modulename. Even when
freeze deems the module necessary it will not be included in the
application.
<DT> <code>optional</code>
<DD> Include a module if it can be found, but don't complain if it can't.
</DL>
There is actually a fourth way that macfreeze can operate: it can be used
to generate only the resource file containing the compiled <code>PYC</code>
resources. This may be useful if you have embedded Python in your own
application. The resource file generated is the same as for the CodeWarrior
generation process. <p>
<h2>Freezing with CodeWarrior</h2>
To freeze with CodeWarrior you need CodeWarrior, obviously, and a full
source distribution of Python. You select the <em>Codewarrior source and
project</em> option. You specify an output folder, which is by default
the name of your script with <code>.py</code> removed and
<code>build.</code> prepended. If the output folder does not exist yet
it is created, and a template project file and bundle resource file are
deposited there. Next, a source file <code>macfreezeconfig.c</code> is
created which includes all builtin modules your script uses, and a
resource file <code>frozenmodules.rsrc</code> which contains the
<code>PYC</code> resources for all your Python modules. <p>
The project expects to live in a folder one level below the Python root
folder, so the next thing you should do is move the build folder there.
It is a good idea to leave an alias with the same name in the original
location: when you run freeze again it will regenerate the
<code>frozenmodules.rsrc</code> file but not the project and bundle
files. This is probably what you want: if you modify your python sources
you have to re-freeze, but you may have changed the project and bundle
files, so you don't want to regenerate them. <p>
An alternative is to leave the build folder where it is, but then you
have to adapt the search path in the project. <p>
The project is set up to include all the standard builtin modules, but
the CW linker is smart enough to exclude any object code that isn't
referenced. Still, it may be worthwhile to remove any sources for
modules that you are sure are not used to cut back on compilation time.
You may also want to examine the various resource files (for Tcl/Tk, for
instance): the loader has no way to know that these aren't used. <p>
You may also need to add sourcefiles if your script uses non-standard
builtin modules, like anything from the <code>Extensions</code> folder. <p>
The <code>frozenbundle.rsrc</code> resource file contains the bundle
information. It is almost identical to the bundle file used for applets,
with the exception that it sets the <code>sys.path</code> initialization
to <code>$(APPLICATION)</code> only. This means that all modules will only
be looked for in PYC resources in your application. <p>
</BODY>
</HTML>
/*
** InterslipLib - Routines to talk to InterSLIP. Version 1.1, 31-Oct-1995.
**
**
** (c) Jack Jansen, CWI, 1995 <jack@cwi.nl>
*/
#include <Devices.h>
#include "InterslipLib.h"
static CntrlParam iopb;
static short refnum = -1;
OSErr is_open()
{
if ( refnum >= 0 ) return 0;
return OpenDriver("\p.InterSLIP", &refnum);
}
OSErr is_connect()
{
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 2;
return PBControlImmed((ParmBlkPtr)&iopb);
}
OSErr is_disconnect()
{
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 3;
return PBControlImmed((ParmBlkPtr)&iopb);
}
OSErr is_status(long *status, long *msgseqnum, StringPtr *msg)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 4;
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
return err;
csp = (long *)&iopb.csParam;
*status = csp[0];
*msgseqnum = csp[1];
*msg = (unsigned char *)csp[2];
return 0;
}
OSErr is_getconfig(long *baudrate, long *flags,
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 6;
csp = (long *)&iopb.csParam;
csp[2] = (long)idrvnam;
csp[3] = (long)odrvnam;
csp[4] = (long)cfgnam;
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
return err;
*baudrate = csp[0];
*flags = csp[1];
return 0;
}
OSErr is_setconfig(long baudrate, long flags,
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 7;
csp = (long *)&iopb.csParam;
csp[0] = baudrate;
csp[1] = flags;
csp[2] = (long)idrvnam;
csp[3] = (long)odrvnam;
csp[4] = (long)cfgnam;
return PBControlImmed((ParmBlkPtr)&iopb);
}
/*
** InterSLIP API.
*/
#include <Types.h>
/* States */
#define IS_IDLE 0
#define IS_WMODEM 1
#define IS_DIAL 2
#define IS_LOGIN 3
#define IS_RUN 4
#define IS_DISC 5
OSErr is_open(); /* Open InterSLIP driver (optional) */
OSErr is_connect();/* Connect */
OSErr is_disconnect(); /* Disconnect */
OSErr is_status(long *, long *, StringPtr *); /* Get status, msg seq#, msg pointer */
OSErr is_getconfig(long *, long *, Str255 , Str255 , Str255 ); /* get config */
OSErr is_setconfig(long , long , Str255 , Str255 , Str255 ); /* set config */
/***********************************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "Python.h"
#include "InterslipLib.h"
#include "macglue.h"
static PyObject *ErrorObject;
/* ----------------------------------------------------- */
static char pyis_open__doc__[] =
"Load the interslip driver (optional)"
;
static PyObject *
pyis_open(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_open();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_connect__doc__[] =
"Tell the driver to start a connect"
;
static PyObject *
pyis_connect(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_connect();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_disconnect__doc__[] =
"Tell the interslip driver to start a disconnect"
;
static PyObject *
pyis_disconnect(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_disconnect();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_status__doc__[] =
"Return (numeric_status, message_seqnum, message_string) status tuple"
;
static PyObject *
pyis_status(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long status, seqnum;
StringPtr message;
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_status(&status, &seqnum, &message);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
return Py_BuildValue("iiO&", (int)status, (int)seqnum, PyMac_BuildStr255, message);
}
static char pyis_getconfig__doc__[] =
"Return configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
;
static PyObject *
pyis_getconfig(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long baudrate, flags;
Str255 idrvname, odrvname, cfgname;
OSErr err;
int ibaud, obaud;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_getconfig(&baudrate, &flags, idrvname, odrvname, cfgname);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
ibaud = (baudrate >> 16) & 0xffff;
obaud = baudrate & 0xffff;
return Py_BuildValue("iiiO&O&O&", ibaud, obaud, (int)flags, PyMac_BuildStr255, idrvname,
PyMac_BuildStr255, odrvname, PyMac_BuildStr255, cfgname);
}
static char pyis_setconfig__doc__[] =
"Set configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
;
static PyObject *
pyis_setconfig(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long baudrate;
int flags;
Str255 idrvname, odrvname, cfgname;
OSErr err;
int ibaud, obaud;
if (!PyArg_ParseTuple(args, "iiiO&O&O&", &ibaud, &obaud, &flags, PyMac_GetStr255, idrvname,
PyMac_GetStr255, odrvname, PyMac_GetStr255, cfgname))
return NULL;
baudrate = (ibaud << 16) | obaud;
err = is_setconfig(baudrate, (long)flags, idrvname, odrvname, cfgname);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
/* List of methods defined in the module */
static struct PyMethodDef pyis_methods[] = {
{"open", pyis_open, 1, pyis_open__doc__},
{"connect", pyis_connect, 1, pyis_connect__doc__},
{"disconnect", pyis_disconnect, 1, pyis_disconnect__doc__},
{"status", pyis_status, 1, pyis_status__doc__},
{"getconfig", pyis_getconfig, 1, pyis_getconfig__doc__},
{"setconfig", pyis_setconfig, 1, pyis_setconfig__doc__},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initinterslip) */
static char interslip_module_documentation[] =
""
;
void
initinterslip()
{
PyObject *m, *d;
/* Create the module and add the functions */
m = Py_InitModule4("interslip", pyis_methods,
interslip_module_documentation,
(PyObject*)NULL,PYTHON_API_VERSION);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyString_FromString("interslip.error");
PyDict_SetItemString(d, "error", ErrorObject);
/* XXXX Add constants here */
PyDict_SetItemString(d, "IDLE", PyInt_FromLong(IS_IDLE));
PyDict_SetItemString(d, "WMODEM", PyInt_FromLong(IS_WMODEM));
PyDict_SetItemString(d, "DIAL", PyInt_FromLong(IS_DIAL));
PyDict_SetItemString(d, "LOGIN", PyInt_FromLong(IS_LOGIN));
PyDict_SetItemString(d, "RUN", PyInt_FromLong(IS_RUN));
PyDict_SetItemString(d, "DISC", PyInt_FromLong(IS_DISC));
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module interslip");
}
This diff is collapsed.
This diff is collapsed.
import Printing
from Carbon import Qd
from Carbon import Fm
from Carbon import Res
# some constants
PostScriptBegin = 190 # Set driver state to PostScript
PostScriptEnd = 191 # Restore QuickDraw state
PostScriptHandle = 192 # PostScript data referenced in handle
CHUNK_SIZE = 0x8000 # max size of PicComment
def PostScript(text):
"""embed text as plain PostScript in print job."""
handle = Res.Resource('')
Qd.PicComment(PostScriptBegin, 0, handle)
while text:
chunk = text[:CHUNK_SIZE]
text = text[CHUNK_SIZE:]
handle.data = chunk
Qd.PicComment(PostScriptHandle, len(chunk), handle)
handle.data = ''
Qd.PicComment(PostScriptEnd, 0, handle)
# create a new print record
printrecord = Printing.NewTPrintRecord()
# open the printer
Printing.PrOpen()
try:
# initialize print record with default values
Printing.PrintDefault(printrecord)
# page setup, ok is 0 when user cancelled
ok = Printing.PrStlDialog(printrecord)
if not ok:
raise KeyboardInterrupt
# at this stage, you should save the print record in your document for later
# reference.
# print job dialog, ok is 0 when user cancelled
ok = Printing.PrJobDialog(printrecord)
if not ok:
raise KeyboardInterrupt
# once per document
port = Printing.PrOpenDoc(printrecord)
# port is the Printer's GrafPort, it is also the current port, so no need to Qd.SetPort(port)
try:
# start printing a page
# XXX should really look up what pages to print by
# inspecting the print record.
Printing.PrOpenPage(port, None)
try:
# use QuickDraw like in any other GrafPort
Qd.FrameRect((10, 250, 100, 500))
Qd.FrameRect((10, 510, 100, 600))
Qd.MoveTo(10, 100)
Qd.TextSize(50)
Qd.TextFont(Fm.GetFNum("Helvetica"))
Qd.DrawString("It rreally works!")
Qd.MoveTo(10, 150)
Qd.TextSize(20)
Qd.DrawString("(and now for a little PostScript...)")
# example PostScript code
ps = """
% the coordinate system is the quickdraw one, which is flipped
% compared to the default PS one. That means text will appear
% flipped when used directly from PostScript.
% As an example we start by defining a custom scalefont operator
% that corrects this.
/myscalefont{[exch 0 0 2 index neg 0 0]makefont}def
0.75 setgray
0 0 moveto
0 30 lineto 10000 30 lineto
10000 0 lineto closepath fill
0 setgray
5 25 moveto /Courier findfont 20 myscalefont setfont
(Printed with PostScript!) show
2 setlinewidth [10 10 5 10] 0 setdash 5 5 moveto 400 0 rlineto stroke
"""
# embed the PostScript code in the print job
PostScript(ps)
finally:
# when done with the page
Printing.PrClosePage(port)
finally:
# when done with the document
Printing.PrCloseDoc(port)
finally:
# when done printing
Printing.PrClose()
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment