diff options
author | Jack Jansen <jack.jansen@cwi.nl> | 2001-02-11 01:08:04 (GMT) |
---|---|---|
committer | Jack Jansen <jack.jansen@cwi.nl> | 2001-02-11 01:08:04 (GMT) |
commit | 8a38714ba05a3734f812bb1bbebdc527732a22bc (patch) | |
tree | 90f53048b00a22476549e1ef3c38470fca66e3c7 /Mac/Python | |
parent | 6a9aec47b72cf42bed0f845e751eb243f85b43d6 (diff) | |
download | cpython-8a38714ba05a3734f812bb1bbebdc527732a22bc.zip cpython-8a38714ba05a3734f812bb1bbebdc527732a22bc.tar.gz cpython-8a38714ba05a3734f812bb1bbebdc527732a22bc.tar.bz2 |
Bit the bullet and added a private GUSISIOUX for Python. This makes the delayconsole and keepopen code neater. Also tells Sioux to behave better with events, and handles cmd-. during print better. The pythonpreferences have also changed due to this.
Diffstat (limited to 'Mac/Python')
-rw-r--r-- | Mac/Python/macglue.c | 19 | ||||
-rw-r--r-- | Mac/Python/macmain.c | 42 | ||||
-rw-r--r-- | Mac/Python/pyGUSISIOUX.cp | 209 |
3 files changed, 258 insertions, 12 deletions
diff --git a/Mac/Python/macglue.c b/Mac/Python/macglue.c index ade635e..6321421 100644 --- a/Mac/Python/macglue.c +++ b/Mac/Python/macglue.c @@ -539,6 +539,25 @@ PyErr_CheckSignals() return 0; } +#if 0 +/* +** This routine is called if we know that an external library yielded +** to background tasks, so we shouldn't count that time in our computation +** of how much CPU we used. +** This happens with SIOUX, and the routine is called from our modified +** GUSISIOUX. +*/ +void +PyMac_LibraryDidYield(int howlong) +{ + unsigned long maxnextcheck = (unsigned long)LMGetTicks() + schedparams.check_interval; + + schedparams.next_check = schedparams.next_check + howlong; + if (schedparams.next_check > maxnextcheck ) + schedparams.next_check = maxnextcheck; +} +#endif + int PyOS_InterruptOccurred() { diff --git a/Mac/Python/macmain.c b/Mac/Python/macmain.c index 8dfbdaf..09d8648 100644 --- a/Mac/Python/macmain.c +++ b/Mac/Python/macmain.c @@ -53,9 +53,9 @@ extern int ccommand(char ***); #ifdef USE_MAC_SHARED_LIBRARY extern PyMac_AddLibResources(void); #endif -#ifdef USE_GUSI -#include "GUSISIOUX.h" -#endif +//#ifdef USE_GUSI +//#include "GUSISIOUX.h" +//#endif #define STARTUP "PythonStartup" @@ -71,6 +71,14 @@ short PyMac_AppRefNum; /* RefNum of application resource fork */ static char **orig_argv; static int orig_argc; +/* A flag which remembers whether the user has acknowledged all the console +** output (by typing something) +*/ +#define STATE_UNKNOWN 0 +#define STATE_LASTREAD 1 +#define STATE_LASTWRITE 2 +int console_output_state = STATE_UNKNOWN; + PyMac_PrefRecord PyMac_options; static void Py_Main(int, char **); /* Forward */ @@ -544,10 +552,18 @@ Py_Main(argc, argv) void PyMac_OutputSeen() { -#ifdef GUSISIOUX_STATE_UNKNOWN - gusisioux_state = GUSISIOUX_STATE_LASTREAD; -#endif + console_output_state = STATE_LASTREAD; +} + +/* +** Set the "unseen output" flag +*/ +void +PyMac_OutputNotSeen() +{ + console_output_state = STATE_LASTWRITE; } + /* ** Terminate application @@ -569,15 +585,11 @@ PyMac_Exit(status) keep = 0; break; case POPT_KEEPCONSOLE_OUTPUT: -#ifdef GUSISIOUX_STATE_UNKNOWN - if (gusisioux_state == GUSISIOUX_STATE_LASTWRITE || - gusisioux_state == GUSISIOUX_STATE_UNKNOWN ) + if (console_output_state == STATE_LASTWRITE || + console_output_state == STATE_UNKNOWN ) keep = 1; else keep = 0; -#else - keep = 1; -#endif break; case POPT_KEEPCONSOLE_ERROR: keep = (status != 0); @@ -636,3 +648,9 @@ Py_GetExecPrefix() { return PyMac_GetPythonDir(); } + +int +PyMac_GetDelayConsoleFlag() +{ + return (int)PyMac_options.delayconsole; +}
\ No newline at end of file diff --git a/Mac/Python/pyGUSISIOUX.cp b/Mac/Python/pyGUSISIOUX.cp new file mode 100644 index 0000000..795e10e --- /dev/null +++ b/Mac/Python/pyGUSISIOUX.cp @@ -0,0 +1,209 @@ +/* +** Modified version of GUSISIOUX.cp especially for Python. +** Changes (by Jack): +** - Optionally delay the console window until something is written to it. +** - Tell the upper layers whether the last command was a read or a write. +** - Tell SIOUX not to use WaitNextEvent (both Python and SIOUX trying to be +** nice to background apps means we're yielding almost 100% of the time). +** - Make sure signals are processed when returning from read/write. +*/ +#define GUSI_SOURCE +#include "GUSIInternal.h" +#include "GUSISIOUX.h" +#include "GUSIDevice.h" +#include "GUSIDescriptor.h" +#include "GUSIBasics.h" +#include "GUSIDiag.h" +//#ifndef WITHOUT_JACK_MODS +//#include "GUSIConfig.h" +//#endif + +#include <LowMem.h> + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <console.h> + +#include "Python.h" +#include "macglue.h" +extern Boolean SIOUXUseWaitNextEvent; + +class GUSISIOUXSocket : public GUSISocket { +public: + ~GUSISIOUXSocket(); + + +ssize_t read(const GUSIScatterer & buffer); +ssize_t write(const GUSIGatherer & buffer); +virtual int ioctl(unsigned int request, va_list arg); +virtual int fstat(struct stat * buf); +virtual int isatty(); +bool select(bool * canRead, bool * canWrite, bool *); + + static GUSISIOUXSocket * Instance(); +private: + static GUSISIOUXSocket * sInstance; + + GUSISIOUXSocket(); + bool initialized; + void Initialize(); + bool fDelayConsole; +}; +class GUSISIOUXDevice : public GUSIDevice { +public: + static GUSISIOUXDevice * Instance(); + + +virtual bool Want(GUSIFileToken & file); +virtual GUSISocket * open(GUSIFileToken &, int flags); +private: + GUSISIOUXDevice() {} + + static GUSISIOUXDevice * sInstance; +}; +GUSISIOUXSocket * GUSISIOUXSocket::sInstance; + +GUSISIOUXSocket * GUSISIOUXSocket::Instance() +{ + if (!sInstance) + if (sInstance = new GUSISIOUXSocket) + sInstance->AddReference(); + + return sInstance; +} +// This declaration lies about the return type +extern "C" void SIOUXHandleOneEvent(EventRecord *userevent); + +GUSISIOUXSocket::GUSISIOUXSocket() +{ + if (PyMac_GetDelayConsoleFlag()) + fDelayConsole = true; + else + fDelayConsole = false; + if ( fDelayConsole ) + initialized = 0; + else + Initialize(); + /* Tell the upper layers there's no unseen output */ + PyMac_OutputSeen(); +} + +void +GUSISIOUXSocket::Initialize() +{ + initialized = 1; + InstallConsole(0); + GUSISetHook(GUSI_EventHook+nullEvent, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+mouseDown, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+mouseUp, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+updateEvt, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+diskEvt, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+activateEvt, (GUSIHook)SIOUXHandleOneEvent); + GUSISetHook(GUSI_EventHook+osEvt, (GUSIHook)SIOUXHandleOneEvent); +} +GUSISIOUXSocket::~GUSISIOUXSocket() +{ + if ( !initialized ) return; + RemoveConsole(); +} +ssize_t GUSISIOUXSocket::read(const GUSIScatterer & buffer) +{ + if ( !initialized ) Initialize(); + GUSIStdioFlush(); + PyMac_OutputSeen(); + return buffer.SetLength( + ReadCharsFromConsole((char *) buffer.Buffer(), (int)buffer.Length())); + GUSIContext::Yield(kGUSIPoll); +} +ssize_t GUSISIOUXSocket::write(const GUSIGatherer & buffer) +{ + ssize_t rv; + + if ( !initialized ) Initialize(); + PyMac_OutputNotSeen(); + SIOUXUseWaitNextEvent = false; + rv = WriteCharsToConsole((char *) buffer.Buffer(), (int)buffer.Length()); + GUSIContext::Yield(kGUSIPoll); + return rv; +} +int GUSISIOUXSocket::ioctl(unsigned int request, va_list) +{ + switch (request) { + case FIOINTERACTIVE: + return 0; + default: + return GUSISetPosixError(EOPNOTSUPP); + } +} +int GUSISIOUXSocket::fstat(struct stat * buf) +{ + GUSISocket::fstat(buf); + buf->st_mode = S_IFCHR | 0666; + + return 0; +} +int GUSISIOUXSocket::isatty() +{ + return 1; +} +static bool input_pending() +{ +#if !TARGET_API_MAC_CARBON + // Jack thinks that completely removing this code is a bit + // too much... + QHdrPtr eventQueue = LMGetEventQueue(); + EvQElPtr element = (EvQElPtr)eventQueue->qHead; + + // now, count the number of pending keyDown events. + while (element != nil) { + if (element->evtQWhat == keyDown || element->evtQWhat == autoKey) + return true; + element = (EvQElPtr)element->qLink; + } +#endif + return false; +} + +bool GUSISIOUXSocket::select(bool * canRead, bool * canWrite, bool *) +{ + if ( !initialized ) Initialize(); + bool cond = false; + if (canRead) + if (*canRead = input_pending()) + cond = true; + if (canWrite) + cond = *canWrite = true; + + return cond; +} +GUSISIOUXDevice * GUSISIOUXDevice::sInstance; +GUSISIOUXDevice * GUSISIOUXDevice::Instance() +{ + if (!sInstance) + sInstance = new GUSISIOUXDevice(); + return sInstance; +} +bool GUSISIOUXDevice::Want(GUSIFileToken & file) +{ + switch (file.WhichRequest()) { + case GUSIFileToken::kWillOpen: + return file.IsDevice() && (file.StrStdStream(file.Path()) > -1); + default: + return false; + } +} +GUSISocket * GUSISIOUXDevice::open(GUSIFileToken &, int) +{ + return GUSISIOUXSocket::Instance(); +} +void GUSISetupConsoleDescriptors() +{ + GUSIDescriptorTable * table = GUSIDescriptorTable::Instance(); + GUSISIOUXSocket * SIOUX = GUSISIOUXSocket::Instance(); + + table->InstallSocket(SIOUX); + table->InstallSocket(SIOUX); + table->InstallSocket(SIOUX); +} |