]> granicus.if.org Git - python/commitdiff
Bit the bullet and added a private GUSISIOUX for Python. This makes the delayconsole...
authorJack Jansen <jack.jansen@cwi.nl>
Sun, 11 Feb 2001 01:08:04 +0000 (01:08 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Sun, 11 Feb 2001 01:08:04 +0000 (01:08 +0000)
Mac/Include/macglue.h
Mac/Include/pythonresources.h
Mac/Lib/pythonprefs.py
Mac/Python/macglue.c
Mac/Python/macmain.c
Mac/Python/pyGUSISIOUX.cp [new file with mode: 0644]
Mac/Resources/pythonpath.r

index 372871e288d9ff84e3d9f071966a5699f5c4a6ca..fa61709c89ad95ce8f309261b94f2c46ad0250aa 100644 (file)
@@ -130,6 +130,8 @@ int PyMac_setfiletype(char *, long, long);          /* Set file creator and type */
 void PyMac_Exit(int);
 void PyMac_InitApplication(void);
 void PyMac_OutputSeen(void);
+void PyMac_OutputNotSeen(void);
+int PyMac_GetDelayConsoleFlag(void);
 #ifdef USE_MAC_APPLET_SUPPORT
 void PyMac_InitApplet(void);
 #endif
index 9bb899833a75a07c568650e07b8b1f08616297c4..29026a88c4083f2b98a26dc5a80d1f421a6ced21 100644 (file)
@@ -137,7 +137,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define PYTHONOPTIONS_ID 228
 #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_OUTPUT 1
 #define   POPT_KEEPCONSOLE_ERROR  2
@@ -158,6 +158,7 @@ typedef struct PyMac_PrefRecord {
        unsigned char   tabwarn;
        unsigned char   nosite;
        unsigned char   nonavservice;
+       unsigned char   delayconsole;
 } PyMac_PrefRecord;
 #endif
 
index 81d095f3f67979a2fa189cf2ea1e9f1e8cf7caf5..0ae3e36915b213098e9ff12787400ba2eee809de 100644 (file)
@@ -16,14 +16,14 @@ OVERRIDE_POPT_ID = 229
 OVERRIDE_GUSI_ID = 10241
 
 # version
-CUR_VERSION=6
+CUR_VERSION=7
 
 preffilename = PstringLoader(AnyResLoader('STR ', resname=PREFNAME_NAME)).load()
 pref_fss = preferencefile(preffilename, 'Pyth', 'pref')
 
 class PoptLoader(VersionLoader):
        def __init__(self, loader):
-               VersionLoader.__init__(self, "bbbbbbbbbbbbb", loader)
+               VersionLoader.__init__(self, "bbbbbbbbbbbbbb", loader)
                
        def versioncheck(self, data):
                if data[0] == CUR_VERSION:
@@ -44,16 +44,11 @@ class GusiLoader:
                tp = self.data[0:4]
                cr = self.data[4:8]
                flags = ord(self.data[9])
-               delay = ((flags & 0x20) == 0x20)
-               return cr, tp, delay
+               return cr, tp
                
-       def save(self, (cr, tp, delay)):
+       def save(self, (cr, tp)):
                flags = ord(self.data[9])
-               if delay:
-                       flags = flags | 0x20
-               else:
-                       flags = flags & ~0x20
-               newdata = tp + cr + self.data[8] + chr(flags) + self.data[10:]
+               newdata = tp + cr + self.data[8:]
                self.loader.save(newdata)
                
 popt_default_default = NullLoader(chr(CUR_VERSION) + 8*'\0')
@@ -85,23 +80,23 @@ class PythonOptions:
                diralias = self.dir.load()
                dirfss, dummy = macfs.RawAlias(diralias).Resolve()
                dict['dir'] = dirfss
-               dict['creator'], dict['type'], dict['delayconsole'] = self.gusi.load()
+               dict['creator'], dict['type'] = self.gusi.load()
                flags = self.popt.load()
                dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
                        dict['unbuffered'], dict['debugging'], dummy, dict['keep_console'], \
                        dict['nointopt'], dict['noargs'], dict['tabwarn'], \
-                       dict['nosite'], dict['nonavservice'] = flags
+                       dict['nosite'], dict['nonavservice'], dict['delayconsole'] = flags
                return dict
                
        def save(self, dict):
                self.path.save(dict['path'])
                diralias = macfs.FSSpec(dict['dir']).NewAlias().data
                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'], \
                        dict['unbuffered'], dict['debugging'], 0, dict['keep_console'], \
                        dict['nointopt'], dict['noargs'], dict['tabwarn'], \
-                       dict['nosite'], dict['nonavservice']
+                       dict['nosite'], dict['nonavservice'], dict['delayconsole']
                self.popt.save(flags)
 
 def AppletOptions(file):
index ade635ed9b4070f668e578cf0c7690c06037e168..63214217205aee5e34a96595ce4d99151a4742df 100644 (file)
@@ -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()
 {
index 8dfbdaf1574897bb9c7f7f2cafa5e47ae18af4bd..09d86486d26aa75c4ed7222c640aab45751faf61 100644 (file)
@@ -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 (file)
index 0000000..795e10e
--- /dev/null
@@ -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);
+}
index 2739b19aed8c232cec20c3d51291e803f8c18fc7..b127d9f9e0532e3a7de5efe63e6b243d7ed19915 100644 (file)
@@ -25,6 +25,7 @@ type 'Popt' {
        byte newStandardExceptions = 0, oldStandardExceptions = 1;
        byte sitePython = 0, noSitePython = 1;
        byte navService = 0, noNavService = 1;
+       byte noDelayConsole = 0, delayConsole = 1;
 };
 
 type 'TMPL' {
@@ -53,6 +54,7 @@ resource 'TMPL' (PYTHONOPTIONS_ID, "Popt") {
                "Old standard exceptions",              'DBYT',
                "No site-python support",               'DBYT',
                "No NavServices in macfs",              'DBYT',
+               "Delay console window",                 'DBYT',
        }
 };
 
@@ -72,6 +74,7 @@ resource 'Popt' (PYTHONOPTIONS_ID, "Options") {
        newStandardExceptions,
        sitePython,
        navService,
+       noDelayConsole,
 };
 
 /* The sys.path initializer */