2 ** Modified version of GUSISIOUX.cp especially for Python.
4 ** - Optionally delay the console window until something is written to it.
5 ** - Tell the upper layers whether the last command was a read or a write.
6 ** - Tell SIOUX not to use WaitNextEvent (both Python and SIOUX trying to be
7 ** nice to background apps means we're yielding almost 100% of the time).
8 ** - Make sure signals are processed when returning from read/write.
11 #include "GUSIInternal.h"
12 #include "GUSISIOUX.h"
13 #include "GUSIDevice.h"
14 #include "GUSIDescriptor.h"
15 #include "GUSIBasics.h"
17 //#ifndef WITHOUT_JACK_MODS
18 //#include "GUSIConfig.h"
25 #include <sys/ioctl.h>
31 extern Boolean SIOUXUseWaitNextEvent;
33 static PyReadHandler sInConsole = 0L;
34 static PyWriteHandler sOutConsole = 0L;
35 static PyWriteHandler sErrConsole = 0L;
37 inline bool hasCustomConsole(void) { return sInConsole != 0L; }
39 class GUSISIOUXSocket : public GUSISocket {
44 ssize_t read(const GUSIScatterer & buffer);
45 ssize_t write(const GUSIGatherer & buffer);
46 virtual int ioctl(unsigned int request, va_list arg);
47 virtual int fstat(struct stat * buf);
49 bool select(bool * canRead, bool * canWrite, bool *);
51 static GUSISIOUXSocket * Instance(int fd);
53 GUSISIOUXSocket(int fd);
54 static bool initialized;
55 static void Initialize();
58 class GUSISIOUXDevice : public GUSIDevice {
60 static GUSISIOUXDevice * Instance();
63 virtual bool Want(GUSIFileToken & file);
64 virtual GUSISocket * open(GUSIFileToken &, int flags);
68 static GUSISIOUXDevice * sInstance;
71 GUSISIOUXSocket * GUSISIOUXSocket::Instance(int fd)
73 return new GUSISIOUXSocket(fd);
75 // This declaration lies about the return type
76 extern "C" void SIOUXHandleOneEvent(EventRecord *userevent);
78 bool GUSISIOUXSocket::initialized = false;
80 GUSISIOUXSocket::GUSISIOUXSocket(int fd) : fFd(fd)
82 if (!hasCustomConsole()) {
83 if (!PyMac_GetDelayConsoleFlag() && !initialized)
85 /* Tell the upper layers there's no unseen output */
91 GUSISIOUXSocket::Initialize()
93 if(!initialized && !hasCustomConsole())
97 GUSISetHook(GUSI_EventHook+nullEvent, (GUSIHook)SIOUXHandleOneEvent);
98 GUSISetHook(GUSI_EventHook+mouseDown, (GUSIHook)SIOUXHandleOneEvent);
99 GUSISetHook(GUSI_EventHook+mouseUp, (GUSIHook)SIOUXHandleOneEvent);
100 GUSISetHook(GUSI_EventHook+updateEvt, (GUSIHook)SIOUXHandleOneEvent);
101 GUSISetHook(GUSI_EventHook+diskEvt, (GUSIHook)SIOUXHandleOneEvent);
102 GUSISetHook(GUSI_EventHook+activateEvt, (GUSIHook)SIOUXHandleOneEvent);
103 GUSISetHook(GUSI_EventHook+osEvt, (GUSIHook)SIOUXHandleOneEvent);
107 GUSISIOUXSocket::~GUSISIOUXSocket()
109 if ( !initialized || hasCustomConsole() )
115 ssize_t GUSISIOUXSocket::read(const GUSIScatterer & buffer)
117 if(hasCustomConsole())
120 return buffer.SetLength(
121 sInConsole((char *) buffer.Buffer(), (int)buffer.Length()));
126 if ( !initialized ) Initialize();
129 PyMac_RaiseConsoleWindow();
130 return buffer.SetLength(
131 ReadCharsFromConsole((char *) buffer.Buffer(), (int)buffer.Length()));
132 GUSIContext::Yield(kGUSIPoll);
134 ssize_t GUSISIOUXSocket::write(const GUSIGatherer & buffer)
136 if(hasCustomConsole())
139 return sOutConsole((char *) buffer.Buffer(), (int)buffer.Length());
141 return sErrConsole((char *) buffer.Buffer(), (int)buffer.Length());
148 if ( !initialized ) Initialize();
149 PyMac_OutputNotSeen();
150 SIOUXUseWaitNextEvent = false;
151 rv = WriteCharsToConsole((char *) buffer.Buffer(), (int)buffer.Length());
152 GUSIContext::Yield(kGUSIPoll);
155 int GUSISIOUXSocket::ioctl(unsigned int request, va_list)
161 return GUSISetPosixError(EOPNOTSUPP);
164 int GUSISIOUXSocket::fstat(struct stat * buf)
166 GUSISocket::fstat(buf);
167 buf->st_mode = S_IFCHR | 0666;
171 int GUSISIOUXSocket::isatty()
175 static bool input_pending()
180 bool GUSISIOUXSocket::select(bool * canRead, bool * canWrite, bool *)
182 if ( !initialized ) Initialize();
185 if (*canRead = input_pending())
188 cond = *canWrite = true;
192 GUSISIOUXDevice * GUSISIOUXDevice::sInstance;
193 GUSISIOUXDevice * GUSISIOUXDevice::Instance()
196 sInstance = new GUSISIOUXDevice();
199 bool GUSISIOUXDevice::Want(GUSIFileToken & file)
201 switch (file.WhichRequest()) {
202 case GUSIFileToken::kWillOpen:
203 return file.IsDevice() && (file.StrStdStream(file.Path()) > -1);
208 GUSISocket * GUSISIOUXDevice::open(GUSIFileToken &, int)
210 return GUSISIOUXSocket::Instance(1);
212 void GUSISetupConsoleDescriptors()
214 GUSIDescriptorTable * table = GUSIDescriptorTable::Instance();
216 table->InstallSocket(GUSISIOUXSocket::Instance(0));
217 table->InstallSocket(GUSISIOUXSocket::Instance(1));
218 table->InstallSocket(GUSISIOUXSocket::Instance(2));
221 void PyMac_SetConsoleHandler(PyReadHandler stdinH, PyWriteHandler stdoutH, PyWriteHandler stderrH)
223 if(stdinH && stdoutH && stderrH)
226 sOutConsole = stdoutH;
227 sErrConsole = stderrH;
231 long PyMac_DummyReadHandler(char *buffer, long n)
236 long PyMac_DummyWriteHandler(char *buffer, long n)