mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
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.
This commit is contained in:
parent
6a9aec47b7
commit
8a38714ba0
7 changed files with 274 additions and 27 deletions
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,11 +552,19 @@ 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;
|
||||
}
|
||||
209
Mac/Python/pyGUSISIOUX.cp
Normal file
209
Mac/Python/pyGUSISIOUX.cp
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue