#include "ET++.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Application.h" #include "Document.h" #include "Class.h" #include "Storage.h" #include "FileDialog.h" #include "ObjectTable.h" #include "ClassManager.h" #include "ClipBoard.h" #include "ProgEnv.h" #include "Buttons.h" #include "IAC.h" #include "WindowSystem.h" #include "Env.h" #include "ProgressDialog.h" #include "FileData.h" #include "Alert_e.h" #include "Error.h" #include "Menu.h" #include "String.h" #include "Box.h" #include "MenuBar.h" #include "System.h" #include "ET_stdio.h" Application *gApplication; ClipBoard *gClipBoard; int gArgc; char **gArgv; const char *gVersion= "Version 3.0b, 3/1/93"; const char *gCopyright= "\ \2511987-1989 Dept. for Comp. Science, University of Zurich\n\ \2511989-1993 Information Technology Lab (UBILAB), Union Bank of Switzerland"; //---- ApplErrorHandler -------------------------------------------------------- static void ApplErrorHandler(int level, bool, const char *location, const char *msg) { gApplication->DoOnError(level, location, msg); } //---- AppRpcConnection -------------------------------------------------------- class AppRpcConnection : public IAC { EvtHandler *handler; public: AppRpcConnection(EvtHandler *eh) { handler= eh; } int Dispatch(int, const char*, const char*, int, char*&, int&); }; int AppRpcConnection::Dispatch(int from, const char *req, const char *buf, int len, char *&ret, int &retlen) { if (handler) handler->ExtCommand(from, (char*)req, (char*)buf, len, ret, retlen); return 0; } //---- Application ------------------------------------------------------------- NewAbstractMetaImpl(Application,Manager, (T(lastWindowPos), TP(mainDocumentType), TP(fileDialog), TS(gVersion), TS(gCopyright), TP(gApplication), TP(gClipBoard), TVP(gArgv,gArgc), TP(gClassManager))); FileDialog *Application::fileDialog; Application::Application(int ac, char **av, const Symbol &dt) : Manager(BaseName(av[0])) { if (gApplication) Error("Application", "only one Application !!"); gApplication= this; gArgc= ac; gArgv= av; mainDocumentType= &dt; ETInit(ac, av); WindowSystem::WSInit(); SetErrorHandler(ApplErrorHandler); lastWindowPos= Env::GetValue("Document.Position", Point(150, 100)); } Application::~Application() { if (gApplication == this) gApplication= 0; SafeDelete(fileDialog); } FileDialog *Application::MakeFileDialog() { return new FileDialog; } Manager *Application::NewManager(const Symbol &type) { Manager *mp= DoMakeManager(type); // let user make his managers if (mp) { AddManager(mp); mp->Show(); } return mp; } void Application::ParseCommandLine(int argc, char **argv) { for (int i= 1; i < argc;) { if (argv[i][0] == '-') { int n= DoParseOptions(argv[i], argv[i+1]); if (n > 0) i+= n; else i++; } else OpenDocument(argv[i++]); } } int Application::DoParseOptions(char *arg0, char*) { if (arg0[0] == '-' && arg0[1] == 'E') { if (arg0[2] == 'e') gProgEnv->Start(); if (arg0[2] == 'h') gProgEnv->ShowInHierarchy(this->IsA()); return 1; } return 0; } void Application::RemoveManager(Manager *mp) { Manager::RemoveManager(mp); if (Size() <= 0 && !IsOpen()) Quit(); } const char *Application::ProgramName() { return BaseName(gProgname); } Point Application::GetInitialWindowPos() { Point p= lastWindowPos; lastWindowPos+= Point(40, 30); return p; } void Application::About() { ShowAlert(eAlertSun, "%s\n%s\n%s", ProgramName(), gVersion, gCopyright); } Command *Application::DoMenuCommand(int cmd) { switch(cmd) { case cNEW: NewManager(GetMainDocumentType()); break; case cQUIT: Quit(); break; case cABOUT: About(); break; case cOPEN: OpenDocument(0); break; default: Manager::DoMenuCommand(cmd); break; } return gNoChanges; } void Application::DoSetupMenu(Menu *m) { Manager::DoSetupMenu(m); switch (m->GetId()) { case cFILEMENU: m->EnableItems(cOPEN, cNEW, cQUIT, cABOUT, 0); break; } } void Application::Control(int i, int part, void *val) { SendDown(i, part, val); } void Application::ExtCommand(int from, char *rq, char *args, int len, char *&ret, int &retlen) { char req[100], *cp; strcpy(req, rq); cp= strchr(req, ':'); if (cp) { *cp++= 0; if (strcmp(req, "document") == 0) { Iter next(MakeIterator()); Manager *first= (Manager*)next(); if (first) first->ExtCommand(from, cp, args, len, ret, retlen); } else if (strcmp(req, "application") == 0) { if (strcmp(cp, "quit") == 0) Quit(); else if (strcmp(cp, "about") == 0) About(); else if (strcmp(cp, "new") == 0) NewManager(GetMainDocumentType()); else if (strcmp(cp, "open") == 0) OpenDocument(args); else if (strcmp(cp, "inspect") == 0) Inspect(); ret= "ok"; } } gWindowSystem->Update(); } void Application::Quit() { if (Close()) gSystem->ExitControl(); } Manager *Application::DoMakeManager(Symbol type) { return DoMakeDocuments(type); } bool Application::OpenDocument(const char *name) { bool rc= FALSE, dodelete= FALSE; Data *data; Manager *mp; if (name == 0) { if (fileDialog == 0) fileDialog= MakeFileDialog(); if (fileDialog->ShowInWindow(eFDRead, 0, this) != cIdOk) return FALSE; name= fileDialog->FileName(); data= fileDialog->GetData(); } else { data= new FileData(name); dodelete= TRUE; } if (!CanOpen(data)) { ShowAlert(eAlertNote, "Cannot handle document @I%s@P (%s)\n", data->ShortName(), data->Type().AsString()); } else { mp= DoMakeManager(data->Type()); // let user make his managers if (mp) { AddManager(mp); mp->Show(); ((Document*)mp)->LoadData(data, TRUE); gWindowSystem->Update(); rc= TRUE; } } if (dodelete) delete data; return rc; } bool Application::CanOpen(Data *data) { if (GetMainDocumentType() == cDocTypeUndef) return TRUE; if (GetMainDocumentType() == data->Type()) return TRUE; if (GetMainDocumentType() == cDocTypeAscii && data->IsAscii()) return TRUE; return FALSE; } void Application::MakeInitManager() { if (Size() <= 0) NewManager(GetMainDocumentType()); } int Application::Run() { gRpc= new AppRpcConnection(this); gClipBoard= new ClipBoard; gProgress= new ProgressImpl; ParseCommandLine(gArgc, gArgv); MakeInitManager(); Open(); gSystem->Control(); SetErrorHandler(DefaultErrorHandler); SafeDelete(gClipBoard); SafeDelete(gRpc); SafeDelete(gProgress); return 0; } void Application::DoOnError(int level, const char *location, const char *msg) { static bool inError= FALSE; if (level < Env::GetValue("System.IgnoreLevel", cError) || inError) return; inError= TRUE; char *type= "Warning"; if (level >= cFatal) type= "Fatal"; else if (level >= cSysError) type= "SysError"; else if (level >= cError) type= "Error"; fprintf(stderr, "%s: %s in <%s>: %s\n", ProgramName(), type, location, msg); if (level >= cError) { int r= ShowAlert(eAlertError, "%s: %s\nin @B%s@B: %s", ProgramName(), type, location, msg); switch (r) { case cIdIgnore: break; case cIdAbort: gSystem->Abort(); break; case cIdInspect: Debug(); break; } } inError= FALSE; } void Application::Debug() { gRpc->SendTo(0, "attachto", form("%s %d", gProgPath, gSystem->GetPid())); gSystem->Wait(15000); //ShowAlert(eAlertError, "%s: Debugger did not attach\n", ProgramName()); } //---- obsolete ---------------------------------------------------------------- Document *Application::DoMakeDocuments(Symbol) { return 0; } void Application::NewDocument(Symbol) { } //---- external calls of ET++PE ------------------------------------------------ extern "C" int ETPE_Enter(Object *op); static int callCount; int ETPE_Enter(Object *op) { int level= callCount++; Port *p= GrGetPort(); if (op == 0) op= gApplication; if (!ObjectTable::PtrIsValid(op)) { fprintf(stderr, "ET++PE: 0x%x is not an instance of Object\n", (int)op); return 0; } op->Inspect(); //---- nested event-loop while (callCount > level && !gQuitApp) gSystem->InnerLoop(); if (gQuitApp) callCount= 0; fprintf(stderr, "\nETPE: Exit\n"); GrSetPort(p); return level; } int gCallCount(int d) { callCount+= d; return callCount; }