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:
Jack Jansen 2001-02-11 01:08:04 +00:00
parent 6a9aec47b7
commit 8a38714ba0
7 changed files with 274 additions and 27 deletions

View File

@ -130,6 +130,8 @@ int PyMac_setfiletype(char *, long, long); /* Set file creator and type */
void PyMac_Exit(int); void PyMac_Exit(int);
void PyMac_InitApplication(void); void PyMac_InitApplication(void);
void PyMac_OutputSeen(void); void PyMac_OutputSeen(void);
void PyMac_OutputNotSeen(void);
int PyMac_GetDelayConsoleFlag(void);
#ifdef USE_MAC_APPLET_SUPPORT #ifdef USE_MAC_APPLET_SUPPORT
void PyMac_InitApplet(void); void PyMac_InitApplet(void);
#endif #endif

View File

@ -137,7 +137,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define PYTHONOPTIONS_ID 228 #define PYTHONOPTIONS_ID 228
#define PYTHONOPTIONSOVERRIDE_ID 229 #define PYTHONOPTIONSOVERRIDE_ID 229
#define POPT_VERSION_CURRENT 6 /* Current version number */ #define POPT_VERSION_CURRENT 7 /* Current version number */
#define POPT_KEEPCONSOLE_NEVER 0 #define POPT_KEEPCONSOLE_NEVER 0
#define POPT_KEEPCONSOLE_OUTPUT 1 #define POPT_KEEPCONSOLE_OUTPUT 1
#define POPT_KEEPCONSOLE_ERROR 2 #define POPT_KEEPCONSOLE_ERROR 2
@ -158,6 +158,7 @@ typedef struct PyMac_PrefRecord {
unsigned char tabwarn; unsigned char tabwarn;
unsigned char nosite; unsigned char nosite;
unsigned char nonavservice; unsigned char nonavservice;
unsigned char delayconsole;
} PyMac_PrefRecord; } PyMac_PrefRecord;
#endif #endif

View File

@ -16,14 +16,14 @@ OVERRIDE_POPT_ID = 229
OVERRIDE_GUSI_ID = 10241 OVERRIDE_GUSI_ID = 10241
# version # version
CUR_VERSION=6 CUR_VERSION=7
preffilename = PstringLoader(AnyResLoader('STR ', resname=PREFNAME_NAME)).load() preffilename = PstringLoader(AnyResLoader('STR ', resname=PREFNAME_NAME)).load()
pref_fss = preferencefile(preffilename, 'Pyth', 'pref') pref_fss = preferencefile(preffilename, 'Pyth', 'pref')
class PoptLoader(VersionLoader): class PoptLoader(VersionLoader):
def __init__(self, loader): def __init__(self, loader):
VersionLoader.__init__(self, "bbbbbbbbbbbbb", loader) VersionLoader.__init__(self, "bbbbbbbbbbbbbb", loader)
def versioncheck(self, data): def versioncheck(self, data):
if data[0] == CUR_VERSION: if data[0] == CUR_VERSION:
@ -44,16 +44,11 @@ class GusiLoader:
tp = self.data[0:4] tp = self.data[0:4]
cr = self.data[4:8] cr = self.data[4:8]
flags = ord(self.data[9]) flags = ord(self.data[9])
delay = ((flags & 0x20) == 0x20) return cr, tp
return cr, tp, delay
def save(self, (cr, tp, delay)): def save(self, (cr, tp)):
flags = ord(self.data[9]) flags = ord(self.data[9])
if delay: newdata = tp + cr + self.data[8:]
flags = flags | 0x20
else:
flags = flags & ~0x20
newdata = tp + cr + self.data[8] + chr(flags) + self.data[10:]
self.loader.save(newdata) self.loader.save(newdata)
popt_default_default = NullLoader(chr(CUR_VERSION) + 8*'\0') popt_default_default = NullLoader(chr(CUR_VERSION) + 8*'\0')
@ -85,23 +80,23 @@ class PythonOptions:
diralias = self.dir.load() diralias = self.dir.load()
dirfss, dummy = macfs.RawAlias(diralias).Resolve() dirfss, dummy = macfs.RawAlias(diralias).Resolve()
dict['dir'] = dirfss dict['dir'] = dirfss
dict['creator'], dict['type'], dict['delayconsole'] = self.gusi.load() dict['creator'], dict['type'] = self.gusi.load()
flags = self.popt.load() flags = self.popt.load()
dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \ dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
dict['unbuffered'], dict['debugging'], dummy, dict['keep_console'], \ dict['unbuffered'], dict['debugging'], dummy, dict['keep_console'], \
dict['nointopt'], dict['noargs'], dict['tabwarn'], \ dict['nointopt'], dict['noargs'], dict['tabwarn'], \
dict['nosite'], dict['nonavservice'] = flags dict['nosite'], dict['nonavservice'], dict['delayconsole'] = flags
return dict return dict
def save(self, dict): def save(self, dict):
self.path.save(dict['path']) self.path.save(dict['path'])
diralias = macfs.FSSpec(dict['dir']).NewAlias().data diralias = macfs.FSSpec(dict['dir']).NewAlias().data
self.dir.save(diralias) self.dir.save(diralias)
self.gusi.save((dict['creator'], dict['type'], dict['delayconsole'])) self.gusi.save((dict['creator'], dict['type']))
flags = dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \ flags = dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
dict['unbuffered'], dict['debugging'], 0, dict['keep_console'], \ dict['unbuffered'], dict['debugging'], 0, dict['keep_console'], \
dict['nointopt'], dict['noargs'], dict['tabwarn'], \ dict['nointopt'], dict['noargs'], dict['tabwarn'], \
dict['nosite'], dict['nonavservice'] dict['nosite'], dict['nonavservice'], dict['delayconsole']
self.popt.save(flags) self.popt.save(flags)
def AppletOptions(file): def AppletOptions(file):

View File

@ -539,6 +539,25 @@ PyErr_CheckSignals()
return 0; 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 int
PyOS_InterruptOccurred() PyOS_InterruptOccurred()
{ {

View File

@ -53,9 +53,9 @@ extern int ccommand(char ***);
#ifdef USE_MAC_SHARED_LIBRARY #ifdef USE_MAC_SHARED_LIBRARY
extern PyMac_AddLibResources(void); extern PyMac_AddLibResources(void);
#endif #endif
#ifdef USE_GUSI //#ifdef USE_GUSI
#include "GUSISIOUX.h" //#include "GUSISIOUX.h"
#endif //#endif
#define STARTUP "PythonStartup" #define STARTUP "PythonStartup"
@ -71,6 +71,14 @@ short PyMac_AppRefNum; /* RefNum of application resource fork */
static char **orig_argv; static char **orig_argv;
static int orig_argc; 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; PyMac_PrefRecord PyMac_options;
static void Py_Main(int, char **); /* Forward */ static void Py_Main(int, char **); /* Forward */
@ -544,11 +552,19 @@ Py_Main(argc, argv)
void void
PyMac_OutputSeen() PyMac_OutputSeen()
{ {
#ifdef GUSISIOUX_STATE_UNKNOWN console_output_state = STATE_LASTREAD;
gusisioux_state = GUSISIOUX_STATE_LASTREAD;
#endif
} }
/*
** Set the "unseen output" flag
*/
void
PyMac_OutputNotSeen()
{
console_output_state = STATE_LASTWRITE;
}
/* /*
** Terminate application ** Terminate application
*/ */
@ -569,15 +585,11 @@ PyMac_Exit(status)
keep = 0; keep = 0;
break; break;
case POPT_KEEPCONSOLE_OUTPUT: case POPT_KEEPCONSOLE_OUTPUT:
#ifdef GUSISIOUX_STATE_UNKNOWN if (console_output_state == STATE_LASTWRITE ||
if (gusisioux_state == GUSISIOUX_STATE_LASTWRITE || console_output_state == STATE_UNKNOWN )
gusisioux_state == GUSISIOUX_STATE_UNKNOWN )
keep = 1; keep = 1;
else else
keep = 0; keep = 0;
#else
keep = 1;
#endif
break; break;
case POPT_KEEPCONSOLE_ERROR: case POPT_KEEPCONSOLE_ERROR:
keep = (status != 0); keep = (status != 0);
@ -636,3 +648,9 @@ Py_GetExecPrefix()
{ {
return PyMac_GetPythonDir(); return PyMac_GetPythonDir();
} }
int
PyMac_GetDelayConsoleFlag()
{
return (int)PyMac_options.delayconsole;
}

209
Mac/Python/pyGUSISIOUX.cp Normal file
View 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);
}

View File

@ -25,6 +25,7 @@ type 'Popt' {
byte newStandardExceptions = 0, oldStandardExceptions = 1; byte newStandardExceptions = 0, oldStandardExceptions = 1;
byte sitePython = 0, noSitePython = 1; byte sitePython = 0, noSitePython = 1;
byte navService = 0, noNavService = 1; byte navService = 0, noNavService = 1;
byte noDelayConsole = 0, delayConsole = 1;
}; };
type 'TMPL' { type 'TMPL' {
@ -53,6 +54,7 @@ resource 'TMPL' (PYTHONOPTIONS_ID, "Popt") {
"Old standard exceptions", 'DBYT', "Old standard exceptions", 'DBYT',
"No site-python support", 'DBYT', "No site-python support", 'DBYT',
"No NavServices in macfs", 'DBYT', "No NavServices in macfs", 'DBYT',
"Delay console window", 'DBYT',
} }
}; };
@ -72,6 +74,7 @@ resource 'Popt' (PYTHONOPTIONS_ID, "Options") {
newStandardExceptions, newStandardExceptions,
sitePython, sitePython,
navService, navService,
noDelayConsole,
}; };
/* The sys.path initializer */ /* The sys.path initializer */