home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-05-04 | 9.4 KB | 456 lines | [TEXT/MPS ] |
- /*********************************************************************
- Project : MacPerl - Standalone Perl
- File : MPConsole.cp - Console interface for GUSI
- Author : Matthias Neeracher
- Language : MPW C/C++
-
- $Log: MPConsole.cp,v $
- Revision 1.2 1994/05/04 02:49:57 neeri
- Safer Interrupts.
-
- Revision 1.1 1994/02/27 23:04:58 neeri
- Initial revision
-
- Revision 0.2 1993/08/30 00:00:00 neeri
- ShowWindow -> DoShowWindow
-
- Revision 0.1 1993/08/14 00:00:00 neeri
- Remember rectangles
-
- *********************************************************************/
-
- #include "GUSI_P.h"
-
- #include <Resources.h>
- #include <Windows.h>
- #include <Errors.h>
- #include <Folders.h>
- #include <PLStringFuncs.h>
- #include <SysEqu.h>
- #include <OSEvents.h>
-
- #include <ioctl.h>
- #include <sys/types.h>
- #include <Signal.h>
-
- extern "C" {
- #include "MPConsole.h"
-
- #include "MPGlobals.h"
- #include "MPAppleEvents.h"
- #include "MPWindow.h"
- #include "MPFile.h"
- #include "MPMain.h"
- }
-
- #define AF_CONSOLE 17
-
- class MPConsoleSocket; // That's what this file's all about
-
- class MPConsoleSocket : public Socket {
- friend class MPConsoleSocketDomain;
- friend void CloseConsole(Ptr cookie);
- friend void HarvestConsole(DPtr doc, MPConsoleSocket * sock);
- friend int GUSIConsoleSpin(spin_msg msg, long arg);
-
- MPConsoleSocket(DPtr window);
-
- virtual ~MPConsoleSocket();
-
- DPtr window;
- Handle input;
- Boolean nonblocking;
- Boolean eof;
- public:
- virtual int read(void * buffer, int buflen);
- virtual int write(void * buffer, int buflen);
- virtual int fcntl(unsigned int cmd, int arg);
- virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
- virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
- virtual void post_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
- virtual int ioctl(unsigned int request, void *argp);
- virtual int isatty();
- };
-
- class MPConsoleSocketDomain : public DeviceSocketDomain {
- MPConsoleSocket * first;
- public:
- MPConsoleSocketDomain() : DeviceSocketDomain(AF_CONSOLE) { }
-
- virtual Socket * open(const char * filename, int oflag);
- };
-
- MPConsoleSocketDomain MPConsoleSockets;
-
- #pragma segment MPConsole
-
- /************************ MPConsoleSocket members ************************/
-
- void HarvestConsole(DPtr doc, MPConsoleSocket * sock)
- {
- HLock((*doc->theText)->hText);
-
- char * chr = *(*doc->theText)->hText + (*doc->theText)->teLength;
- char * end = *(*doc->theText)->hText + doc->u.cons.fence;
-
- if (gGotEof == doc) {
- PtrAndHand(end, sock->input, chr - end);
-
- doc->u.cons.fence = (*doc->theText)->teLength;
- sock->eof = true;
- } else
- while (chr-- > end)
- if (*chr == '\n') {
- PtrAndHand(end, sock->input, ++chr - end);
- doc->u.cons.fence = chr - *(*doc->theText)->hText;
-
- break;
- }
-
- HUnlock((*doc->theText)->hText);
- }
-
- MPConsoleSocket::MPConsoleSocket(DPtr window)
- : window(window)
- {
- nonblocking = false;
- eof = false;
- input = NewHandle(0);
- window->u.cons.cookie = Ptr(this);
- }
-
- void CloseConsole(Ptr cookie)
- {
- if (cookie)
- ((MPConsoleSocket *) cookie)->window = nil;
- }
-
- MPConsoleSocket::~MPConsoleSocket()
- {
- DisposeHandle(input);
-
- if (window)
- window->u.cons.cookie = nil;
- }
-
- int MPConsoleSocket::fcntl(unsigned int cmd, int arg)
- {
- switch (cmd) {
- case F_GETFL:
- if (nonblocking)
- return FNDELAY;
- else
- return 0;
- case F_SETFL:
- if (arg & FNDELAY)
- nonblocking = true;
- else
- nonblocking = false;
-
- return 0;
- default:
- return GUSI_error(EOPNOTSUPP);
- }
- }
-
- int MPConsoleSocket::ioctl(unsigned int request, void *argp)
- {
- switch (request) {
- case FIONBIO:
- nonblocking = (Boolean) *(long *) argp;
-
- return 0;
- case FIONREAD:
- *(unsigned long *) argp = GetHandleSize(input);
-
- return 0;
- case FIOINTERACTIVE:
- return 0;
- case WIOSELECT:
- if (window)
- SelectWindow(window->theWindow);
-
- return 0;
- default:
- return GUSI_error(EOPNOTSUPP);
- }
- }
-
- int MPConsoleSocket::read(void * buffer, int buflen)
- {
- int avail;
-
- avail = int(GetHandleSize(input));
-
- if (!avail) {
- if (eof) {
- eof = false;
-
- return 0;
- }
- if (!window)
- return 0;
- else if (nonblocking)
- return GUSI_error(EWOULDBLOCK);
- else {
- if (!((WindowPeek) window->theWindow)->visible)
- DoShowWindow(window->theWindow);
- if (!((WindowPeek) window->theWindow)->hilited)
- SelectWindow(window->theWindow);
-
- window->u.cons.selected = true;
- ShowWindowStatus();
-
- SPIN(!(avail = int(GetHandleSize(input))) && !eof && window, SP_STREAM_READ, 0);
-
- if (!avail && eof)
- eof = false;
-
- window->u.cons.selected = false;
- ShowWindowStatus();
- }
- }
-
- buflen = min(avail, buflen);
-
- HLock(input);
- memcpy(buffer, *input, buflen);
- if (avail -= buflen)
- memcpy(*input, *input+buflen, avail);
- HUnlock(input);
- SetHandleSize(input, avail);
-
- return buflen;
- }
-
- int MPConsoleSocket::write(void * buffer, int buflen)
- {
- short oldStart;
- short oldEnd;
- int len = buflen;
-
- if (!window)
- return GUSI_error(ESHUTDOWN);
-
- HarvestConsole(window, this);
-
- if (len > window->u.cons.memory) {
- buffer = (void *) (Ptr(buffer) + len - window->u.cons.memory);
- len = window->u.cons.memory;
- }
-
- (*window->theText)->teLength += buflen;
- EnforceMemory(window, window->theText);
- (*window->theText)->teLength -= buflen;
-
- oldStart = (*window->theText)->selStart;
- oldEnd = (*window->theText)->selEnd;
-
- if (oldStart >= window->u.cons.fence)
- oldStart += buflen;
- if (oldEnd >= window->u.cons.fence)
- oldEnd += buflen;
-
- TESetSelect(window->u.cons.fence, window->u.cons.fence, window->theText);
- TEInsert(buffer, buflen, window->theText);
-
- if (!((WindowPeek) window->theWindow)->visible) {
- HideControl(window->vScrollBar);
- HideControl(window->hScrollBar);
-
- DoShowWindow(window->theWindow);
- }
-
- ShowSelect(window);
- DrawPageExtras(window);
-
- TESetSelect(oldStart, oldEnd, window->theText);
-
- if (window->u.cons.fence < 32767)
- window->u.cons.fence += buflen;
-
- return buflen;
- }
-
- static Boolean StatusNeedsUpdate = false;
-
- void MPConsoleSocket::pre_select(Boolean canRead, Boolean, Boolean)
- {
- if (canRead && window) {
- StatusNeedsUpdate = window->u.cons.selected = true;
-
- if (!((WindowPeek) window->theWindow)->visible)
- DoShowWindow(window->theWindow);
- }
- }
-
- void MPConsoleSocket::post_select(Boolean canRead, Boolean, Boolean)
- {
- if (canRead && window)
- StatusNeedsUpdate = window->u.cons.selected = false;
- }
-
- int MPConsoleSocket::select(Boolean * canRead, Boolean * canWrite, Boolean * exception)
- {
- int goodies = 0;
-
- if (StatusNeedsUpdate) {
- ShowWindowStatus();
-
- StatusNeedsUpdate = false;
- }
-
- if (canRead)
- if (*canRead = (GetHandleSize(input) > 0 || eof))
- ++goodies;
-
- if (canWrite) {
- *canWrite = true;
- ++goodies;
- }
-
- if (exception)
- *exception = false;
-
- return goodies;
- }
-
- int MPConsoleSocket::isatty()
- {
- return 1;
- }
-
- /********************* MPConsoleSocketDomain member **********************/
-
- #pragma force_active on
-
- static Boolean spinInstalled = false;
-
- Socket * MPConsoleSocketDomain::open(const char * filename, int flags)
- {
- DPtr doc;
- Socket * sock = nil;
- char title[256];
- Boolean nudoc = false;
-
- strncpy(title, filename, 7);
- title[7] = 0;
-
- if (equalstring(title, (char *) "stdin", false, true)) {
- flags = O_RDONLY;
-
- if (filename[5])
- return (Socket *) TryNextDevice;
- else
- filename += 5;
- } else if (equalstring(title, (char *) "stdout", false, true)) {
- flags = O_WRONLY;
-
- if (filename[6])
- return (Socket *) TryNextDevice;
- else
- filename += 6;
- } else if (equalstring(title, (char *) "console", false, true)) {
- switch (filename[7]) {
- case ':':
- ++filename;
- case 0:
- filename += 7;
- break;
- default:
- return (Socket *) TryNextDevice;
- }
- } else
- return (Socket *) TryNextDevice;
-
- if (*filename) {
- for (doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->kind == kConsoleWindow) {
- getwtitle(doc->theWindow, title);
-
- if (equalstring(title, (char *) filename, false, true)) {
- if (doc->u.cons.cookie)
- sock = (Socket *) doc->u.cons.cookie;
-
- goto found;
- }
- }
-
- nudoc = true;
- doc = NewDocument(false, kConsoleWindow);
-
- setwtitle(doc->theWindow, (char *) filename);
-
- RestoreConsole(doc);
- } else {
- for (doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->kind == kWorksheetWindow) {
- if (doc->u.cons.cookie)
- sock = (Socket *) doc->u.cons.cookie;
-
- goto found;
- }
-
- nudoc = true;
- doc = NewDocument(false, kWorksheetWindow);
-
- SetWTitle(doc->theWindow, StringPtr(CurApName));
-
- RestoreConsole(doc);
- }
-
- found:
- if (!sock) {
- errno = 0;
- sock = new MPConsoleSocket(doc);
-
- if (sock && errno) {
- if (nudoc)
- CloseMyWindow(doc->theWindow);
-
- delete sock;
-
- return nil;
- }
-
- if (!spinInstalled) {
- GUSISetSpin(GUSIConsoleSpin);
-
- spinInstalled = true;
- }
- } else
- ((MPConsoleSocket *)sock)->eof = false;
-
- if (!(flags & 1))
- doc->u.cons.fence = (*doc->theText)->teLength;
- else if (nudoc)
- doc->u.cons.fence = 32767;
-
- return sock;
- }
-
- /********************* A kinder, gentler, spin **********************/
-
- int GUSIConsoleSpin(spin_msg spin, long)
- {
- if (!gInBackground && GUSIInterrupt() && gRunningPerl) {
- FlushEvents(-1, 0);
-
- if (spin == SP_AUTO_SPIN)
- raise(SIGINT);
- else
- return -1;
- }
-
- MainEvent(spin != SP_SELECT && spin != SP_STREAM_READ);
-
- for (DPtr doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->dirty) {
- if (doc->u.cons.cookie)
- HarvestConsole(doc, (MPConsoleSocket *) doc->u.cons.cookie);
- doc->dirty = false;
- }
-
- return 0;
- }
-