1 /* OS/2 PM main program - creates a hidden window, and starts Python
2  * interpreter in a separate thread, so that Python scripts can be
3  * run in PM process space without a console Window.  The interpreter
4  * is incorporated by linking in the Python DLL.
5  *
6  * As it stands, I don't think this is adequate for supporting Python
7  * GUI modules, as the Python thread doesn't have its own message
8  * queue - which is required of threads that want to create/use
9  * PM windows.
10  *
11  * This code owes a lot to "OS/2 Presentation Manager Programming", by
12  * Charles Petzold.
13  *
14  * Andrew MacIntyre <andymac@bullseye.apana.org.au>, August 2001.
15  * Released under the terms of the Python 2.1.1 licence - see the LICENCE
16  * file in the Python v2.1.1 (or later) source distribution.
17  * Copyright assigned to the Python Software Foundation, 2001.
18  */
19 
20 #define INCL_DOS
21 #define INCL_WIN
22 #include <os2.h>
23 #include <process.h>
24 
25 #include "Python.h"
26 
27 /* use structure to pass command line to Python thread */
28 typedef struct
29 {
30     int argc;
31     char **argv;
32     HWND Frame;
33     int running;
34 } arglist;
35 
36 /* make this a global to simplify access.
37  * it should only be set from the Python thread, or by the code that
38  * initiates the Python thread when the thread cannot be created.
39  */
40 int PythonRC;
41 
42 extern DL_EXPORT(int) Py_Main(int, char **);
43 void PythonThread(void *);
44 
45 int
main(int argc,char ** argv)46 main(int argc, char **argv)
47 {
48     ULONG FrameFlags = FCF_TITLEBAR |
49                        FCF_SYSMENU |
50                        FCF_SIZEBORDER |
51                        FCF_HIDEBUTTON |
52                        FCF_SHELLPOSITION |
53                        FCF_TASKLIST;
54     HAB hab;
55     HMQ hmq;
56     HWND Client;
57     QMSG qmsg;
58     arglist args;
59     int python_tid;
60 
61     /* init PM and create message queue */
62     hab = WinInitialize(0);
63     hmq = WinCreateMsgQueue(hab, 0);
64 
65     /* create a (hidden) Window to house the window procedure */
66     args.Frame = WinCreateStdWindow(HWND_DESKTOP,
67                                     0,
68                                     &FrameFlags,
69                                     NULL,
70                                     "PythonPM",
71                                     0L,
72                                     0,
73                                     0,
74                                     &Client);
75 
76     /* run Python interpreter in a thread */
77     args.argc = argc;
78     args.argv = argv;
79     args.running = 0;
80     if (-1 == (python_tid = _beginthread(PythonThread, NULL, 1024 * 1024, &args)))
81     {
82         /* couldn't start thread */
83         WinAlarm(HWND_DESKTOP, WA_ERROR);
84         PythonRC = 1;
85     }
86     else
87     {
88         /* process PM messages, until Python exits */
89         while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
90             WinDispatchMsg(hab, &qmsg);
91         if (args.running > 0)
92             DosKillThread(python_tid);
93     }
94 
95     /* destroy window, shutdown message queue and PM */
96     WinDestroyWindow(args.Frame);
97     WinDestroyMsgQueue(hmq);
98     WinTerminate(hab);
99 
100     return PythonRC;
101 }
102 
PythonThread(void * argl)103 void PythonThread(void *argl)
104 {
105     HAB hab;
106     arglist *args;
107 
108     /* PM initialisation */
109     hab = WinInitialize(0);
110 
111     /* start Python */
112     args = (arglist *)argl;
113     args->running = 1;
114     PythonRC = Py_Main(args->argc, args->argv);
115 
116     /* enter a critical section and send the termination message */
117     DosEnterCritSec();
118     args->running = 0;
119     WinPostMsg(args->Frame, WM_QUIT, NULL, NULL);
120 
121     /* shutdown PM and terminate thread */
122     WinTerminate(hab);
123     _endthread();
124 }
125